package com.ctshk.rpc.order.localfun.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.constant.CurrencyRateExchangeConstant;
import com.ctshk.common.constant.RedisConstants;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.*;
import com.ctshk.common.exception.BusinessException;
import com.ctshk.common.model.PageResponse;
import com.ctshk.common.model.TokenUser;
import com.ctshk.common.utils.*;
//import com.ctshk.common.utils.MailUtil;
import com.ctshk.common.utils.process.ProcessorUtil;
import com.ctshk.rpc.booking.enums.SupplierReserveTypeEnum;
import com.ctshk.rpc.booking.req.system.SupplierOrderSystemFreeCallConfirmReq;
import com.ctshk.rpc.booking.req.system.SystemConfirmReq;
import com.ctshk.rpc.booking.req.system.localfun.add.SupplierOrderSystemLocalFunAddReq;
import com.ctshk.rpc.booking.req.system.localfun.add.SupplierSystemOrderLocalFunAddReq;
import com.ctshk.rpc.booking.req.system.localfun.add.SupplierSystemOrderLocalFunDetailAddReq;
import com.ctshk.rpc.booking.service.ISupplierOrderService;
import com.ctshk.rpc.finance.json.AccountJson;
import com.ctshk.rpc.finance.req.bill.BillAddCollectionReq;
import com.ctshk.rpc.finance.req.bill.BillAddRefundReq;
import com.ctshk.rpc.finance.req.onaccount.RollBackQuotaReq;
import com.ctshk.rpc.finance.req.onaccount.UseQuotaReq;
import com.ctshk.rpc.finance.service.IFinanceBillService;
import com.ctshk.rpc.finance.service.IFinanceOnAccountCurrencyQuotaService;
import com.ctshk.rpc.finance.service.IFinanceOnAccountService;
import com.ctshk.rpc.iotc.dto.OperateBankPreferenceQueryDTO;
import com.ctshk.rpc.iotc.dto.OperatePromotionQueryDTO;
import com.ctshk.rpc.iotc.req.OperateBankConformQueryReq;
import com.ctshk.rpc.iotc.req.OperateBankDeductReq;
import com.ctshk.rpc.iotc.req.OperatePromotionConformReq;
import com.ctshk.rpc.iotc.service.IOperateBankPreferenceService;
import com.ctshk.rpc.iotc.service.IOperatePromotionService;
import com.ctshk.rpc.localfun.dto.*;
import com.ctshk.rpc.localfun.req.*;
import com.ctshk.rpc.localfun.service.*;
import com.ctshk.rpc.order.localfun.dto.*;
import com.ctshk.rpc.order.localfun.entity.*;
import com.ctshk.rpc.order.localfun.generator.LocalFunOrderGenerator;
import com.ctshk.rpc.order.localfun.mapper.*;
import com.ctshk.rpc.order.localfun.req.*;
import com.ctshk.rpc.order.localfun.service.ILocalFunOrderReceiptService;
import com.ctshk.rpc.order.localfun.service.ILocalFunOrderService;
import com.ctshk.rpc.order.season.req.CancelStatusReq;
import com.ctshk.rpc.order.season.req.DynamicAffirmOrderReq;
import com.ctshk.rpc.order.season.service.ISeasonOrderService;
import com.ctshk.rpc.starvip.req.TransactionIntegralReq;
import com.ctshk.rpc.starvip.service.IStarVipBusinessService;
import com.ctshk.rpc.system.dto.MainDataCurrencyListDTO;
import com.ctshk.rpc.system.dto.MainDataCurrencyQueryDTO;
import com.ctshk.rpc.system.dto.SysDepartmentDTO;
import com.ctshk.rpc.system.dto.UserDTO;
import com.ctshk.rpc.system.req.MainDataCurrencyListReq;
import com.ctshk.rpc.system.req.MainDataCurrencyUpdateStatusReq;
import com.ctshk.rpc.system.service.IMainDataCurrencyService;
import com.ctshk.rpc.system.service.ISysDepartmentService;
import com.ctshk.rpc.system.service.ISysPermissionService;
import com.ctshk.rpc.system.service.ISysUserService;
import com.ctshk.rpc.workflow.dto.ApprovalCheckDTO;
import com.ctshk.rpc.workflow.dto.ApprovalStartDTO;
import com.ctshk.rpc.workflow.service.ISysApprovalService;
import com.github.houbb.heaven.util.lang.StringUtil;
import com.github.kfcfans.powerjob.client.OhMyClient;
import com.github.kfcfans.powerjob.common.response.ResultDTO;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @Description
 * @Author wansi <gaylen15527491065@yeah.net>
 * @Date 2021/3/29
 */
@Slf4j
@DubboService
public class LocalFunOrderServiceImpl extends ServiceImpl<LocalFunOrderMapper, LocalFunOrder> implements ILocalFunOrderService {

    @Autowired
    private LocalFunOrderMapper localFunOrderMapper;
    @Autowired
    private LocalFunOrderTouristMapper localFunOrderTouristMapper;

    @Autowired
    private LocalFunManualOrderMapper localFunManualOrderMapper;

    @Autowired
    private LocalFunOrderCollectionMapper localFunOrderCollectionMapper;

    @Autowired
    private LocalFunOrderRefundMapper localFunOrderRefundMapper;

    @DubboReference
    private ILocalFunProductService iLocalFunProductService;

    @DubboReference
    private IMainDataCurrencyService iMainDataCurrencyService;

    @DubboReference
    private ISysPermissionService sysPermissionService;

    @DubboReference
    private ILocalFunProductCostStrategySpecAttrService localFunProductCostStrategySpecAttrService;

    @DubboReference
    private ISysUserService iSysUserService;

    @DubboReference
    private ISysDepartmentService iSysDepartmentService;

    @DubboReference
    private ILocalFunOrderReceiptService iLocalFunOrderReceiptService;

    @DubboReference
    private ISupplierOrderService iSupplierOrderService;

    @DubboReference
    private ILocalFunResourceService iLocalFunResourceService;

    @DubboReference
    private ILocalFunProductSaleRecordService localFunProductSaleRecordService;

    @DubboReference
    private ISysApprovalService iSysApprovalService;

    @DubboReference
    private IFinanceBillService iFinanceBillService;

    @DubboReference
    private ISeasonOrderService iSeasonOrderService;

    @DubboReference
    private ILocalFunCostPriceService costPriceService;

    @DubboReference
    private IFinanceOnAccountService iFinanceOnAccountService;
    @DubboReference
    private IFinanceOnAccountCurrencyQuotaService onAccountCurrencyQuotaService;

    @DubboReference
    private IOperatePromotionService operatePromotionService;

    @DubboReference
    IOperateBankPreferenceService operateBankPreferenceService;
    @DubboReference
    private ILocalFunCostPriceService iLocalFunCostPriceService;

    @Value("${schedule.config.domain}")
    private String domain;

    @Value("${schedule.config.app-name}")
    private String appName;

    @Value("${schedule.config.password}")
    private String password;

    @Value("${schedule.job-id.order.localfun}")
    private long jobId;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @DubboReference
    private IStarVipBusinessService iStarVipBusinessService;

    @DubboReference
    private ILocalFunAppProductService iLocalFunAppProductService;
    @DubboReference
    private ILocalFunAppProductService  appProductService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result addOrderInfo(LocalFunAddCheckOrderReq localFunAddCheckOrderReq, TokenUser tokenUser) {

        Integer strategyType = new Integer(2).equals(localFunAddCheckOrderReq.getLocalFunOrderInputCheckReq().getIsAgent()) ? 2 : 1;
        Long relId = new Integer(2).equals(localFunAddCheckOrderReq.getLocalFunOrderInputCheckReq().getIsAgent()) ? localFunAddCheckOrderReq.getLocalFunOrderInputCheckReq().getAgencyId() : tokenUser.getId();
        //校验余票
        if(appProductService.noMoreSurplusNumber(localFunAddCheckOrderReq.getLocalFunOrderInputCheckReq().getProductId(),localFunAddCheckOrderReq.getLocalFunOrderInputCheckReq().getAttr1Id(),
                localFunAddCheckOrderReq.getLocalFunOrderInputCheckReq().getAttr2Id(),strategyType,relId)){

            return Result.failed(SystemError.LOCAL_FUN_18016);
        }
        LocalFunOrderInputCheckReq orderInputCheckReq = localFunAddCheckOrderReq.getLocalFunOrderInputCheckReq();

        //生成订单ID
        long orderId = SnowflakeIdWorker.nextId();
        LocalFunOrderInfo localFunOrderInfo = new LocalFunOrderInfo();
        //1.保存订单信息
        saveOrderInfo(orderInputCheckReq, tokenUser, orderId, 1,localFunOrderInfo);
        //2.登记旅客资料
        registerTouristInfo(localFunAddCheckOrderReq.getTouristInfos(),tokenUser.getId(),orderId,orderInputCheckReq.getAttr1Id(),orderInputCheckReq.getAttr2Id(), orderInputCheckReq.getProductId(),localFunOrderInfo);
        //3.扣减库存
        reduceRepository(tokenUser, orderInputCheckReq, orderId);

        OrderInfoDTO orderInfoDTO = new OrderInfoDTO();
        orderInfoDTO.setAttrId1(orderInputCheckReq.getAttr1Id());
        orderInfoDTO.setAttrId2(orderInputCheckReq.getAttr2Id());
        orderInfoDTO.setOrderId(orderId);
        return Result.success(orderInfoDTO);
    }

    /**
     * 减库存
     * @param tokenUser
     * @param orderInputCheckReq
     * @param orderId
     */
    protected void reduceRepository(TokenUser tokenUser, LocalFunOrderInputCheckReq orderInputCheckReq, long orderId) {
        // 1 自营 2代理商
        try {
            Integer channel = orderInputCheckReq.getIsAgent() == null || !new Integer(2).equals(orderInputCheckReq.getIsAgent()) ? 1 : 2;
            CustomDto customSelLine = iLocalFunProductService.getCustomSelLine(orderInputCheckReq.getProductId(), channel, tokenUser.getId(),orderInputCheckReq.getAgencyId());
            localFunProductSaleRecordService.operateStock(LocalFunStockReq.builder().attrId1(orderInputCheckReq.getAttr1Id())
                    .attrId2(orderInputCheckReq.getAttr2Id())
                    .num(orderInputCheckReq.getNum())
                    .userId(tokenUser.getId()).productId(orderInputCheckReq.getProductId()).orderId(orderId)
                    //线下
                    .line(2).channel(channel)
                    .checkType(Objects.isNull(customSelLine)?null:customSelLine.getCheckType())
                    .customId(Objects.isNull(customSelLine)?null:customSelLine.getCustomId())
                    .customName(Objects.isNull(customSelLine)?null:customSelLine.getCustomName()).build());
        } catch (Exception e) {
            log.error("B端减库存失败：{}",e.getMessage());
        }
    }

    /**
     * 清空历史数据
     * @param orderId
     */
    private void deleteHistoryData(Long orderId) {
        localFunOrderMapper.deleteById(orderId);
        localFunOrderTouristMapper.deleteById(orderId);
    }


    /**
     * 查询推广码
     * @return
     */
    private OperatePromotionQueryDTO findPromotionCode(LocalFunOrder localFunOrder) {
        OperatePromotionConformReq callReq = new OperatePromotionConformReq();
        callReq.setActivityCode(localFunOrder.getCouponCode());
        callReq.setTotalPaidIn(localFunOrder.getReceivableAmount());
        callReq.setBusinessType(SystemBusinessType.LOCAL_FUN.getCode());
        callReq.setRelationId(localFunOrder.getProductId());
        callReq.setChannelId(Assist.toLong(localFunOrder.getSource()));
        callReq.setUserId(localFunOrder.getSalesmanId());
        return operatePromotionService.queryConform(callReq).okExist();
    }

    /**
     * 查询银联优惠
     * @return
     */
    private OperateBankPreferenceQueryDTO findBankPreference(LocalFunOrder localFunOrder,String payer,Long payDiscountId) {
        OperateBankConformQueryReq callReq = new OperateBankConformQueryReq();
        callReq.setId(payDiscountId);
        callReq.setBusinessType(SystemBusinessType.LOCAL_FUN.getCode());
        callReq.setRelationId(localFunOrder.getProductId());
        callReq.setChannelId(Assist.toLong(localFunOrder.getSource()));
        callReq.setUserId(localFunOrder.getSalesmanId());
        callReq.setTotalPaidIn(localFunOrder.getReceivableAmount());
        callReq.setCardNumber(payer);
        return operateBankPreferenceService.queryConform(callReq).okExist();
    }


    /**
     * 新增外挂单
     *
     * @param localFunManualOrderReq 新增外挂单入参
     * @param id 用户id
     * @return 返回值
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result addManualOrder(LocalFunManualOrderReq localFunManualOrderReq, Long id) {
        try {
            Long manualOrderId = IdWorker.getId();//外挂单订单id
            Long orderId = IdWorker.getId(); //订单id
            LocalFunManualOrder manualOrder = EntityUtil.copy(localFunManualOrderReq, LocalFunManualOrder.class);
            manualOrder.setId(manualOrderId);
            manualOrder.setOrderId(orderId);
            int insertManualOrder = localFunManualOrderMapper.insert(manualOrder);
            if(insertManualOrder < 1){
                throw new BusinessException(SystemError.SYS_437);
            }
            LocalFunOrder localFunOrder = EntityUtil.copy(localFunManualOrderReq, LocalFunOrder.class);
            localFunOrder.setId(orderId);
            localFunOrder.setCreateId(id);
            localFunOrder.setIsDeleted(IsDeletedCode.NO.getCode());
            localFunOrder.setPaymentStatus(OrderPaymentStatus.ALREADY_PAYMENT.getCode());
            localFunOrder.setCancelStatus(NumberConstant.ZERO.getValue());
            localFunOrder.setScheduledStatus(OrderScheduledStatus.RESERVE_SUCCESS.getCode());
            localFunOrder.setSource(OrderSource.CPM.getCode());
            localFunOrder.setProductId(null);//外挂订单没有产品Id
            localFunOrder.setProductType(ProductType.PLUG.getCode());
            int insertOrder = localFunOrderMapper.insert(localFunOrder);
            if(insertOrder < 1){
                throw new BusinessException(SystemError.SYS_437);
            }
            return Result.success();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Result.failed(new BusinessException(SystemError.SYS_500));
    }

    /**
     * 积分兑换港币 ￥
     *
     * @param integral 积分
     * @return 返回值
     */
    @Override
    public Result<LocalFunOrderIntegralExchangeDTO> conversionIntegral(Long integral) {
        LocalFunOrderIntegralExchangeDTO localFunOrderIntegralExchangeDTO = new LocalFunOrderIntegralExchangeDTO();

        MainDataCurrencyListReq mainDataCurrencyListReq = new MainDataCurrencyListReq();
        mainDataCurrencyListReq.setName("HKD");
        PageResponse<MainDataCurrencyListDTO> list = iMainDataCurrencyService.list(mainDataCurrencyListReq);
        List<MainDataCurrencyListDTO> records = list.getRecords();
        if(CollectionUtils.isNotEmpty(records)){
            // 人民币id
            Long id = records.get(0).getId();
            MainDataCurrencyUpdateStatusReq currencyUpdateStatusReq = new MainDataCurrencyUpdateStatusReq();
            currencyUpdateStatusReq.setId(id);
            Result<MainDataCurrencyQueryDTO> queryDTOResult = iMainDataCurrencyService.query(currencyUpdateStatusReq);
            MainDataCurrencyQueryDTO result = queryDTOResult.getData();
            if(null != result){
                // 人民币兑换港币汇率
                BigDecimal crmExchangeRate = result.getCrmExchangeRate();

                // 积分
                Integer integralNum = Integer.valueOf(integral.toString());

                // 积分兑换人民币
                Integer var = integralNum/100;

                BigDecimal money = crmExchangeRate.multiply(BigDecimal.valueOf(var));

                localFunOrderIntegralExchangeDTO.setIntegral(integral);
                localFunOrderIntegralExchangeDTO.setIntegralDeduction(money);
                return Result.success(localFunOrderIntegralExchangeDTO);
            }
        }
        return null;
    }

    /**
     * 根据订单id查询订单信息
     *
     * @param orderId 订单id
     * @return 订单信息
     */
    @Override
    public Result<LocalFunOrderPayQueryInfoDTO> queryOrderInfo(Long orderId) {
        try {
            LocalFunOrder localFunOrder = localFunOrderMapper.selectById(orderId);
            if (null == localFunOrder){
                throw new BusinessException(SystemError.SYS_411);
            }
            // 应收总额
            BigDecimal orderAmount = localFunOrder.getReceivableAmount();
            LocalDateTime time = localFunOrder.getGmtCreate();
            LocalDateTime payDueTime = time.plusMinutes(30);
            LocalFunOrderPayQueryInfoDTO payOrderDTO = new LocalFunOrderPayQueryInfoDTO();
            payOrderDTO.setOrderAmount(orderAmount);
            payOrderDTO.setPayDueTime(payDueTime);
            return Result.success(payOrderDTO);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Result.failed(new BusinessException(SystemError.SYS_500));
    }

    /**
     * 预定中心下单
     *
     * @param payOrderReq 预定中心订单入参
     * @return 返回值
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result payOrder(PayOrderReq payOrderReq,TokenUser user) {
        //订单信息
        LocalFunPayOrderCollectionReq collectionReq = payOrderReq.getReqList().stream().findFirst().orElse(null);

        //1.收款前订单校验
        Result checkResult = checkOrderBeforePay(payOrderReq.getReqList(), collectionReq);
        if (checkResult != null) return checkResult;

        //2.记录收款细节
        createOrderCollection(payOrderReq.getReqList(), user, collectionReq);

        //3.记录收款凭据
        LocalFunOrderReceiptAddReq req = new LocalFunOrderReceiptAddReq();
        req.setOrderId(collectionReq.getOrderId());
        iLocalFunOrderReceiptService.add(req,user);
        LocalFunOrder localFunOrder = baseMapper.selectById(collectionReq.getOrderId());
        Result<LocalFunResourceDetailDTO> result = iLocalFunResourceService.productDetail(localFunOrder.getProductId());

        //4.挂账 代理下单
        Result result1 = callFinanceOnAccount(payOrderReq.getReqList(), localFunOrder, user, result);
        if (result1.getCode() != 0){
            return result1;
        }

        //5.生成供应预订单
        Result result2 = callSupplierOrder(user, collectionReq.getOrderId(), localFunOrder, result);
        if (result2.getCode() != 0){
            return result1;
        }

        //6.修改订单状态，返回产品信息
        Result<LocalFunResourceDetailDTO> dtoResult = updateOrderStatus(collectionReq, localFunOrder,collectionReq,result,user,payOrderReq.getReqList());

        //8.认款申请
        Result result3 = iFinanceBillService.addCollection(obtainCollectionApply(localFunOrder, payOrderReq.getReqList(), dtoResult, user));
        if (result3.getCode() != 0){
            return result1;
        }
        return Result.success(localFunOrder.getId());
    }

    /**
     * 代理下单 挂账
     * @param reqList
     * @param localFunOrder
     * @param user
     * @param result
     */
    private Result callFinanceOnAccount(List<LocalFunPayOrderCollectionReq> reqList, LocalFunOrder localFunOrder, TokenUser user, Result<LocalFunResourceDetailDTO> result) {
        //代理下单
        if(localFunOrder.getIsAgent() == 2){
            if(CollectionUtils.isEmpty(reqList)) {
                return Result.failed(SystemError.LOCAL_FUN_18020);
            }
            List<UseQuotaReq> useQuotaReqs = Lists.newArrayListWithExpectedSize(8);
            for(LocalFunPayOrderCollectionReq collectionReq : reqList){
                //支付页面 选择挂账才会走挂账
                if(PayRefundMethod.AC.getId().equals(collectionReq.getCollectionWayId())){

                    //校驗代理是否有掛賬額度
                    checkQuotasMore(collectionReq,localFunOrder);

                    UseQuotaReq useQuotaReq = new UseQuotaReq();
                    //账号为代理下单公司的ID
                    useQuotaReq.setAccountId(localFunOrder.getAgencyId());
                    useQuotaReq.setAccountType(1);
                    useQuotaReq.setAmount(collectionReq.getCollectionAmount());
                    //收款单号
                    useQuotaReq.setBillNumber(collectionReq.getCollectionNumber());
                    useQuotaReq.setBusinessType(SystemBusinessType.LOCAL_FUN.getCode());
                    useQuotaReq.setCollectionWayId(collectionReq.getCollectionWayId());
                    useQuotaReq.setCollectionWayName(collectionReq.getCollectionWay());
                    useQuotaReq.setCollectionTime(LocalDateTime.now());
//                    useQuotaReq.setCollectionVoucherJson(Lists.newArrayList(collectionReq.getCollectionCertificateJson()));
                    useQuotaReq.setContactMobile(localFunOrder.getContactMobile());

                    BigDecimal exchangeRate = iMainDataCurrencyService.getExchangeRate(collectionReq.getCurrency(), CurrencyRateExchangeConstant.MARKET_EXCHANGE_RATE_);
                    useQuotaReq.setExchangeRate(exchangeRate.doubleValue());

                    useQuotaReq.setCurrencyId(collectionReq.getCurrencyId());
                    useQuotaReq.setCurrencyName(collectionReq.getCurrency());
                    useQuotaReq.setUserId(user.getId());
                    UserDTO userDTO = iSysUserService.queryCacheUser(localFunOrder.getCreateId());
                    if(userDTO != null){
                        useQuotaReq.setDeptId(userDTO.getDeptId());
                    }

                    if(result.getData() != null){
                        LocalFunResourceDetailDTO productInfo = result.getData();
                        useQuotaReq.setProductId(localFunOrder.getProductId());
                        useQuotaReq.setProductName(productInfo.getName());
                        useQuotaReq.setProductNumber(productInfo.getProductCode());
                        useQuotaReq.setSaleOrderId(localFunOrder.getId());
                        useQuotaReq.setSaleOrderNumber(localFunOrder.getOrderNumber());
                        useQuotaReq.setSaleUserId(localFunOrder.getSalesmanId());
                        useQuotaReq.setSaleUserName(localFunOrder.getSalesmanName());
                    }
                    useQuotaReqs.add(useQuotaReq);
                }
            }
            if(CollectionUtils.isNotEmpty(useQuotaReqs)){
                Result useQuotaResult = onAccountCurrencyQuotaService.useQuota(useQuotaReqs);
                if (useQuotaResult.getCode() != 0){
                    return useQuotaResult;
                }
            }
        }
        return Result.success();
    }

    /**
     * 校驗 掛賬額度是否夠用
     * @param collectionReq
     * @param localFunOrder
     */
    private void checkQuotasMore(LocalFunPayOrderCollectionReq collectionReq, LocalFunOrder localFunOrder) {
        com.ctshk.rpc.finance.req.onaccount.QueryQuotaReq queryQuotaReq = new com.ctshk.rpc.finance.req.onaccount.QueryQuotaReq();
        queryQuotaReq.setCurrencyId(collectionReq.getCurrencyId());
        queryQuotaReq.setAccountId(localFunOrder.getAgencyId());
        Result<com.ctshk.rpc.finance.dto.onaccount.QueryQuotaDTO> result = onAccountCurrencyQuotaService.queryQuota(queryQuotaReq);
        if(result.getCode() != 0){
            throw new BusinessException(SystemError.LOCAL_FUN_18008);
        }
        com.ctshk.rpc.finance.dto.onaccount.QueryQuotaDTO resultData = result.getData();
        if(resultData != null){
            if(resultData.getAvailableAmount().compareTo(collectionReq.getCollectionAmount()) < 0){
                throw new BusinessException(SystemError.LOCAL_FUN_18008);
            }
        }
    }

    /**
     * 修改订单状态
     * @param collectionReq
     * @param localFunOrder
     * @param req
     * @param result
     * @param user
     * @return
     */
    private Result<LocalFunResourceDetailDTO> updateOrderStatus(LocalFunPayOrderCollectionReq collectionReq, LocalFunOrder localFunOrder, LocalFunPayOrderCollectionReq req, Result<LocalFunResourceDetailDTO> result, TokenUser user,  List<LocalFunPayOrderCollectionReq> reqList) {
        UpdateWrapper<LocalFunOrder> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda().eq(LocalFunOrder::getId,collectionReq.getOrderId());
        updateWrapper.lambda().set(LocalFunOrder::getModifiedId,user.getId());
        updateWrapper.lambda().set(LocalFunOrder::getGmtModified, LocalDateTime.now());
        updateWrapper.lambda().set(LocalFunOrder::getPaymentStatus, OrderPaymentStatus.ALREADY_PAYMENT.getCode());
        Result<LocalFunResourceDetailDTO> dtoResult = iLocalFunResourceService.productDetail(localFunOrder.getProductId());
        if(dtoResult.getData() != null){
            LocalFunResourceDetailDTO entity = dtoResult.getData();
            // 下单后，立即确认，当前自行确认成功 ，二次确认：其他地方手动确认
            //立即确认
            if(entity.getBookConfirm() == 1){
                updateWrapper.lambda().set(LocalFunOrder::getScheduledStatus, OrderScheduledStatus.RESERVE_SUCCESS.getCode());
                updateWrapper.lambda().set(LocalFunOrder::getGmtModified,LocalDateTime.now());
            }else {
                updateWrapper.lambda().set(LocalFunOrder::getScheduledStatus, OrderScheduledStatus.CONFIRM_RESERVE.getCode());
            }
        }

        double sum = reqList.stream().mapToDouble(localFunPayOrderCollectionReq -> localFunPayOrderCollectionReq.getCollectionAmount().doubleValue()).sum();
        updateWrapper.lambda().set(LocalFunOrder::getOrderAmount, sum);

        //银联优惠
        if (BConst.ONE.equals(req.getIsUnionpayDiscount())) {
            if (localFunOrder.getIntegral() != null || Assist.isNotBlank(localFunOrder.getCouponDeduction())) {
                //使用了会员积分或优惠券，无法使用银联优惠
                throw new BusinessException(SystemError.AIREXPRESS_ORDER_60025);
            }
            try {
                //查询银联优惠
                OperateBankPreferenceQueryDTO bankPreferenceDTO = findBankPreference(localFunOrder, req.getPayer(),req.getUnionpayDiscountId());
                log.info("银联优惠:{}",bankPreferenceDTO.getDiscount());
                //扣减银优惠
                deductBankPreference(localFunOrder, bankPreferenceDTO,result,user);

                //银联优惠 订单金额-银联优惠
                BigDecimal orderAmount = localFunOrder.getReceivableAmount();
                orderAmount = orderAmount.subtract(bankPreferenceDTO.getDiscount());
                updateWrapper.lambda().set(LocalFunOrder::getOrderAmount, orderAmount);
            } catch (BusinessException e) {
                log.error("使用银联优惠扣减失败：{}",e.getMessage());
            }
        }

        baseMapper.update(null,updateWrapper);
        return dtoResult;
    }

    /**
     * 扣减银联优惠
     */
    private void deductBankPreference(LocalFunOrder localFunOrder, OperateBankPreferenceQueryDTO mainDto, Result<LocalFunResourceDetailDTO> result, TokenUser user) {
        OperateBankDeductReq callReq = new OperateBankDeductReq();
        callReq.setCardNumber(null);
        callReq.setId(mainDto.getId());
        callReq.setTotalPaidIn(localFunOrder.getReceivableAmount());
        callReq.setBusinessType(SystemBusinessType.LOCAL_FUN.getCode());
        callReq.setRelationId(localFunOrder.getProductId());
        if(result != null && result.getData() != null){
            callReq.setProductNumber(result.getData().getProductCode());
        }
        callReq.setProductName(localFunOrder.getProductName());
        callReq.setDiscountObjectId(null);
        callReq.setChannelId(Assist.toLong(localFunOrder.getSource()));

        operateBankPreferenceService.deduct(callReq, user);
    }



    /**
     * 获取收款认款申请请求参数
     * @param localFunOrder
     * @param reqList
     * @param dtoResult
     * @param user
     * @return
     */
    private List<BillAddCollectionReq> obtainCollectionApply(LocalFunOrder localFunOrder, List<LocalFunPayOrderCollectionReq> reqList, Result<LocalFunResourceDetailDTO> dtoResult, TokenUser user) {
        if(CollectionUtils.isNotEmpty(reqList)){
            return reqList.stream().map(entity->{
                BillAddCollectionReq req = new BillAddCollectionReq();
                req.setSaleOrderId(localFunOrder.getId());
                //单号
                req.setBillNumber(entity.getCollectionNumber());
                req.setSaleOrderNumber(localFunOrder.getOrderNumber());
                //业务类型
                req.setBusinessType(SystemBusinessType.LOCAL_FUN.getCode());
                req.setCollectionAmount(entity.getCollectionAmount());
                req.setCollectionTime(LocalDateTime.now());
                req.setCollectionTypeId(CollectionTypeIdCode.FULL.getCode());
                req.setCollectionTypeName(CollectionTypeIdCode.FULL.getMsg());
                req.setCurrencyId(entity.getCurrencyId());
                req.setCurrencyName(entity.getCurrency());
                req.setProductId(Lists.newArrayList(localFunOrder.getProductId()));
                UserDTO userDTO = iSysUserService.queryCacheUser(user.getId());
                req.setSaleUserId(user.getId());
                req.setSaleUserName(userDTO.getFullName());
                req.setCollectionWayId(entity.getCollectionWayId());
                req.setCollectionWayName(entity.getCollectionWay());
                //汇率
                BigDecimal exchangeRate = iMainDataCurrencyService.getExchangeRate(req.getCurrencyName(), CurrencyRateExchangeConstant.MARKET_EXCHANGE_RATE_);
                req.setExchangeRate(exchangeRate.doubleValue());

                //产品名称、产品编号
                if(dtoResult.getData() != null) {
                    LocalFunResourceDetailDTO en = dtoResult.getData();
                    req.setProductName(en.getName());
                    req.setProductNumber(en.getProductCode());
                }
                //销售部门
                SysDepartmentDTO sysDepartmentDTO = iSysDepartmentService.queryByUserId(user.getId());
                if(sysDepartmentDTO != null){
                    req.setSaleDeptId(sysDepartmentDTO.getId());
                }

//                //资源信息列表
//                req.setResourceInfo();
//                //收款凭证JSON
//                req.setCollectionVoucherJsonList();
                return req;
            }).collect(Collectors.toList());
        }
        return Lists.newArrayListWithCapacity(1);
    }

    /**
     * 收款记录
     * @param reqList
     * @param user
     * @param collectionReq
     */
    private void createOrderCollection(List<LocalFunPayOrderCollectionReq> reqList, TokenUser user, LocalFunPayOrderCollectionReq collectionReq) {
        for (LocalFunPayOrderCollectionReq orderCollectionReq : reqList) {
            LocalFunOrderCollection localFunOrderCollection = EntityUtil.copy(orderCollectionReq, LocalFunOrderCollection.class);
            localFunOrderCollection.setId(SnowflakeIdWorker.nextId());
            localFunOrderCollection.setOrderId(collectionReq.getOrderId());
            String collectionNumber = LocalFunOrderGenerator.getCollectionNumber();
            orderCollectionReq.setCollectionNumber(collectionNumber);
            localFunOrderCollection.setCollectionNumber(collectionNumber);
            localFunOrderCollection.setCreateId(user.getId());
            localFunOrderCollection.setGmtCreate(LocalDateTime.now());
            localFunOrderCollection.setGmtModified(LocalDateTime.now());
            localFunOrderCollection.setSalerId(user.getId());
            localFunOrderCollection.setSalerName(user.getUsername());
            String collectionCertificate = orderCollectionReq.getCollectionCertificateJson();
            if(StringUtils.isNotEmpty(collectionCertificate)){
                String collectionCertificateJson = JSON.toJSONString(collectionCertificate);
                localFunOrderCollection.setCollectionCertificateJson(collectionCertificateJson);
            }
            localFunOrderCollectionMapper.insert(localFunOrderCollection);
        }
    }

    /**
     * 生成供应预订单
     * @param currentUser
     * @param orderId
     * @param localFunOrder
     * @param result
     */
    private Result callSupplierOrder(TokenUser currentUser, Long orderId, LocalFunOrder localFunOrder, Result<LocalFunResourceDetailDTO> result) {
        // 生成供应预订单
        SupplierOrderSystemLocalFunAddReq supplierOrderSystemAirExpressAddReq = new SupplierOrderSystemLocalFunAddReq();
        supplierOrderSystemAirExpressAddReq.setOrderType(1);
        supplierOrderSystemAirExpressAddReq.setSupplierOrderType("1");
        supplierOrderSystemAirExpressAddReq.setBusinessType(SystemBusinessType.LOCAL_FUN.getCode());
        supplierOrderSystemAirExpressAddReq.setTotalFee(localFunOrder.getOrderAmount());
        supplierOrderSystemAirExpressAddReq.setPayableAmount(localFunOrder.getReceivableAmount());
        supplierOrderSystemAirExpressAddReq.setSaleNumber(localFunOrder.getOrderNumber());
        supplierOrderSystemAirExpressAddReq.setConfirmStatus(localFunOrder.getScheduledStatus());
        supplierOrderSystemAirExpressAddReq.setReserveTypeId(SupplierReserveTypeEnum.LOCAL_FUN.getId());

        MainDataCurrencyQueryDTO currencyEntity = iMainDataCurrencyService.getExchangeCurrencyEntity("HKD", CurrencyRateExchangeConstant.MARKET_EXCHANGE_RATE_);
        supplierOrderSystemAirExpressAddReq.setCurrencyId(currencyEntity.getId());
        supplierOrderSystemAirExpressAddReq.setCurrency("HKD");
        supplierOrderSystemAirExpressAddReq.setSupplierType(1L);
        supplierOrderSystemAirExpressAddReq.setSaleType(SalesMethod.SINGLE_SALE.getCode());
        supplierOrderSystemAirExpressAddReq.setReserveStatus(localFunOrder.getScheduledStatus());
        supplierOrderSystemAirExpressAddReq.setSupplierOrderNumber(localFunOrder.getOrderNumber());

        if(result.getData() != null){
            LocalFunResourceDetailDTO detailDTO = result.getData();
            supplierOrderSystemAirExpressAddReq.setProductNumber(detailDTO.getProductCode());
            supplierOrderSystemAirExpressAddReq.setProductName(detailDTO.getName());
            supplierOrderSystemAirExpressAddReq.setSupplierId(detailDTO.getSupplierId());
            supplierOrderSystemAirExpressAddReq.setSupplierName(detailDTO.getSupplierName());
            supplierOrderSystemAirExpressAddReq.setProductType(detailDTO.getSourceType());

            UserDTO userDTO = iSysUserService.loadUserByParam(detailDTO.getChargeUserId(), 1);
            supplierOrderSystemAirExpressAddReq.setDepartmentId(userDTO.getDeptId());
            supplierOrderSystemAirExpressAddReq.setDepartment(userDTO.getDept());

            //二次确认
            if (result.getData().getBookConfirm() == 2) {
                supplierOrderSystemAirExpressAddReq.setReserveStatus(OrderScheduledStatus.CONFIRM_RESERVE.getCode());
                supplierOrderSystemAirExpressAddReq.setConfirmStatus(SupplierConfirmStatus.UN_CONFIRM.getCode());
            } else {  //立即确认
                supplierOrderSystemAirExpressAddReq.setReserveStatus(OrderScheduledStatus.RESERVE_SUCCESS.getCode());
                supplierOrderSystemAirExpressAddReq.setConfirmStatus(SupplierConfirmStatus.CONFIRMED.getCode());
            }
        }
        supplierOrderSystemAirExpressAddReq.setSupplierSystemOrderLocalFunAddReqList(createLocalFunData(result,localFunOrder,currentUser));
        Result<Long> result1 = iSupplierOrderService.addSystemLocalFun(supplierOrderSystemAirExpressAddReq, currentUser.getId());
        if(result1.getCode() != 0){
            return result1;
        }
        return Result.success();
    }

    /**
     *
     *
     * @param result
     * @param localFunOrder
     * @param currentUser
     * @return
     */
    private List<SupplierSystemOrderLocalFunAddReq> createLocalFunData(Result<LocalFunResourceDetailDTO> result, LocalFunOrder localFunOrder, TokenUser currentUser) {
        List<SupplierSystemOrderLocalFunAddReq> list = Lists.newArrayListWithExpectedSize(10);

        //當地玩樂僅單個產品 添加一個即可 <系统内当地玩乐基础信息>
        SupplierSystemOrderLocalFunAddReq req = new SupplierSystemOrderLocalFunAddReq();
        req.setOrderId(localFunOrder.getId());
        req.setCustomerRemark(localFunOrder.getRemark());
        req.setSupplierRemark(null);
        if(result.getData() != null){
            req.setSuitablePeople(result.getData().getChargeUser());
        }

        QueryWrapper<LocalFunOrderTourist> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(LocalFunOrderTourist::getOrderId,localFunOrder.getId());
        List<LocalFunOrderTourist> localFunOrderTourists = localFunOrderTouristMapper.selectList(queryWrapper);

        //本地玩乐详情列表
        if(CollectionUtils.isNotEmpty(localFunOrderTourists)){
            List<SupplierSystemOrderLocalFunDetailAddReq> addReqs = localFunOrderTourists.stream().map(entity -> {
                SupplierSystemOrderLocalFunDetailAddReq addReq = new SupplierSystemOrderLocalFunDetailAddReq();
                addReq.setAirExpressInfoId(null);
                addReq.setNumber(localFunOrder.getTicketNum());
                addReq.setOrderId(localFunOrder.getId());
                addReq.setPassengerName(entity.getTouristName());

                //門票單價
                if(localFunOrder.getTicketsFee() != null && localFunOrder.getTicketNum() != null){
                    addReq.setPrice(localFunOrder.getTicketsFee().divide(new BigDecimal(localFunOrder.getTicketNum())));
                }
                if (result.getData() != null) {
                    addReq.setProductName(result.getData().getName());
                    addReq.setProductNumber(result.getData().getProductCode());
                }
                return addReq;
            }).collect(Collectors.toList());

            req.setSupplierSystemOrderLocalFunDetailAddReqList(addReqs);
        }
        list.add(req);
        return list;
    }

    /**
     * 下订单之前的校验
     * @param reqList
     * @param collectionReq
     * @return
     */
    private Result checkOrderBeforePay(List<LocalFunPayOrderCollectionReq> reqList, LocalFunPayOrderCollectionReq collectionReq) {
        if (CollectionUtils.isEmpty(reqList)) {
            throw new BusinessException(SystemError.SYS_416);
        }

        LocalFunOrder localFunOrder = baseMapper.selectById(collectionReq.getOrderId());
        //订单金额
        BigDecimal orderAmount = localFunOrder.getReceivableAmount().setScale(2,BigDecimal.ROUND_HALF_UP);
        //支付金额
        BigDecimal orderPayAmount = new BigDecimal(0);
        for (LocalFunPayOrderCollectionReq airOrderCollectionDetailReq : reqList) {
            if(airOrderCollectionDetailReq.getCurrencyId() != null){
                BigDecimal crmExchangeRateByName = getCrmExchangeRateByName(String.valueOf(airOrderCollectionDetailReq.getCurrencyId()));
                orderPayAmount = orderPayAmount.add(airOrderCollectionDetailReq.getCollectionAmount().multiply(crmExchangeRateByName)).setScale(2,BigDecimal.ROUND_HALF_UP);
            }else {
                orderPayAmount = orderPayAmount.add(airOrderCollectionDetailReq.getCollectionAmount()).setScale(2,BigDecimal.ROUND_HALF_UP);
            }
        }

        log.info("订单金额：" + orderAmount + "---收款金额：" + orderPayAmount);
        if(orderAmount.compareTo(orderPayAmount) > 0){
            return  Result.failed(SystemError.AIR_ORDER_15001);
        }

        if(collectionReq.getIsUnionpayDiscount() !=null && collectionReq.getIsUnionpayDiscount().intValue()==NumberConstant.ONE.getValue().intValue()&&
                (null==collectionReq.getUnionpayDiscountId() || collectionReq.getUnionpayDiscountId().intValue()<NumberConstant.ONE.getValue().intValue()) ){
            return  Result.failed(SystemError.AIR_ORDER_15003);
        }
        return null;
    }


    /**
     * 订单中心 - 景点门票列表
     *
     * @param  localFunOrderReq
     * @return LocalFunOrderDTO
     */
    @Override
    public PageResponse<LocalFunOrderDTO> list(LocalFunOrderReq localFunOrderReq,TokenUser tokenUser){
        IPage<LocalFunOrder> localFunOrderIPage = null;
        QueryWrapper<LocalFunOrder> queryWrapper = new QueryWrapper<>();
        //判断是否有权限查看
        if (!GlobalConstants.Role.isAdmin(tokenUser.getUsername())) {
            if (localFunOrderReq.getMenuId() == null) {
                throw new BusinessException(SystemError.SYSTEM_2106);
            }
            Result<List<Long>> permissionResult = sysPermissionService.queryPermission(localFunOrderReq.getMenuId(), tokenUser.getId());
            if (!permissionResult.isSuccess()) {
                SystemError result = SystemError.getDefined(permissionResult.getCode());
                throw new BusinessException(result);
            }
            queryWrapper.lambda().in(LocalFunOrder::getSalesmanId,permissionResult.getData());
        }
        if (StringUtils.isNotBlank(localFunOrderReq.getOrderNumber())){
            queryWrapper.eq("order_number",localFunOrderReq.getOrderNumber());
        }
        if (StringUtils.isNotBlank(localFunOrderReq.getProductType())){
            queryWrapper.eq("product_type",localFunOrderReq.getProductType());
        }
        if (StringUtils.isNotBlank(localFunOrderReq.getScheduledStatus())){
            queryWrapper.eq("scheduled_status",localFunOrderReq.getScheduledStatus());
        }
        if (StringUtils.isNotBlank(localFunOrderReq.getPaymentStatus())){
            queryWrapper.eq("payment_status",localFunOrderReq.getPaymentStatus());
        }
        //创建开始时间-创建结束时间
        if (StringUtils.isNotBlank(localFunOrderReq.getGmtCreateBegin()) && StringUtils.isNotBlank(localFunOrderReq.getGmtCreateEnd())){
            queryWrapper.ge("gmt_create",localFunOrderReq.getGmtCreateBegin());
            queryWrapper.le("gmt_create",localFunOrderReq.getGmtCreateEnd());
        }

        //城市
        if (StringUtils.isNotBlank(localFunOrderReq.getCityId())){
            queryWrapper.lambda().eq(LocalFunOrder::getProductCityId,localFunOrderReq.getCityId());
        }
        //产品名称
        if (StringUtils.isNotBlank(localFunOrderReq.getProductName())){
            queryWrapper.lambda().eq(LocalFunOrder::getProductName,localFunOrderReq.getProductName());
        }
        //产品类型 租车
        if (StringUtils.isNotBlank(localFunOrderReq.getFynType())){
            queryWrapper.lambda().eq(LocalFunOrder::getProductFunType,localFunOrderReq.getFynType());
        }
        //联络人
        if (StringUtils.isNotBlank(localFunOrderReq.getContactName())){
            queryWrapper.like("contact_name",localFunOrderReq.getContactName());
        }
        //订单来源
        if (localFunOrderReq.getSource() != null){
            queryWrapper.like("source",localFunOrderReq.getSource());
        }

        //按照訂單更新時間倒序
        queryWrapper.lambda().orderByDesc(LocalFunOrder::getGmtModified);
        IPage<LocalFunOrder> iPage = new Page<>(localFunOrderReq.getPageNo(), localFunOrderReq.getPageSize());
        localFunOrderIPage = localFunOrderMapper.selectPage(iPage,queryWrapper);
        if (CollectionUtils.isEmpty(localFunOrderIPage.getRecords())) {
            return PageResponse.empty(localFunOrderIPage.getCurrent());
        }
        List<LocalFunOrderDTO> localFunOrderDTOS = EntityUtil.copyList(localFunOrderIPage.getRecords(), LocalFunOrderDTO.class);
        ProcessorUtil.processMore(localFunOrderDTOS,LocalFunOrderDTO.class);

        PageResponse<LocalFunOrderDTO> result = new PageResponse<>(localFunOrderDTOS, localFunOrderIPage.getCurrent() == 1, localFunOrderIPage.getTotal() <= (localFunOrderIPage.getCurrent() * localFunOrderIPage.getSize()), localFunOrderIPage.getTotal(), localFunOrderIPage.getCurrent(), localFunOrderIPage.getSize());
        return result;
    }

    @Override
    public Result<LocalFunOrderDetailDTO> localFunOrderDetail(LocalFunOrderDetailReq localFunOrderDetailReq) {
        LocalFunOrder localFunOrder = localFunOrderMapper.selectById(localFunOrderDetailReq.getOrderId());
        LocalFunOrderDetailDTO localFunOrderDetailDTO = EntityUtil.copy(localFunOrder, LocalFunOrderDetailDTO.class);
        if(localFunOrderDetailDTO.getPaymentStatus() != null && localFunOrderDetailDTO.getScheduledStatus() == null){
            localFunOrderDetailDTO.setOrderStatus(localFunOrderDetailDTO.getPaymentStatus());
        }
        if(localFunOrderDetailDTO.getPaymentStatus() != null && localFunOrderDetailDTO.getScheduledStatus() != null){
            if(localFunOrderDetailDTO.getPaymentStatus() < localFunOrderDetailDTO.getScheduledStatus()){
                localFunOrderDetailDTO.setOrderStatus(localFunOrderDetailDTO.getScheduledStatus());
            }
        }
        LocalFunProductDetailReq localFunProductDetailReq = new LocalFunProductDetailReq();
        localFunProductDetailReq.setId(localFunOrder.getProductId());
        Result<LocalFunProductDetailByIdDTO>  localFunProductDetailByIdDTOResult = iLocalFunProductService.localFunProductDetailByIdDTO(localFunProductDetailReq);
        if(localFunProductDetailByIdDTOResult.isSuccess()){
            LocalFunProductDetailByIdDTO localFunProductDetailByIdDTO = localFunProductDetailByIdDTOResult.getData();
            localFunOrderDetailDTO.setCustomerNotice(localFunProductDetailByIdDTO.getCustomerNotice());
            localFunOrderDetailDTO.setFunName(localFunProductDetailByIdDTO.getFunName());
            localFunOrderDetailDTO.setCityName(localFunProductDetailByIdDTO.getCityName());
            localFunOrderDetailDTO.setName(localFunProductDetailByIdDTO.getName());
        }


        String productTicketsIds = localFunOrder.getProductTicketsId();
        if(StringUtils.isNotEmpty(productTicketsIds)){
            LocalFunProductTicketDetailReq localFunProductTicketDetailReq = new LocalFunProductTicketDetailReq();
            localFunProductTicketDetailReq.setId(productTicketsIds);
            Result<List<LocalFunProductCostStrategySpecAttrDTO>> result = localFunProductCostStrategySpecAttrService.specAttrName(localFunProductTicketDetailReq);
            if(result.isSuccess()){
                localFunOrderDetailDTO.setLocalFunProductCostStrategySpecAttrDTOS(result.getData());
            }

            String[] split = org.apache.dubbo.common.utils.StringUtils.delimitedListToStringArray(productTicketsIds,",");
            List<Long> ids = Arrays.stream(split).filter(id-> org.apache.dubbo.common.utils.StringUtils.isNotEmpty(id) && !"null".equals(id)).map(id -> Long.valueOf(id)).collect(Collectors.toList());
            localFunOrderDetailDTO.setAttrId1(ids.get(0));
            if(ids.size() > 1){
                localFunOrderDetailDTO.setAttrId1(ids.get(1));
            }
        }
        localFunOrderDetailDTO.setRealityAmount(localFunOrder.getOrderAmount());
        localFunOrderDetailDTO.setReceivableAmount(localFunOrder.getReceivableAmount());

        List<LocalFunOrderRefund> localFunOrderRefunds = localFunOrderRefundMapper.selectList(
                Wrappers.<LocalFunOrderRefund>lambdaQuery().eq(LocalFunOrderRefund::getOrderId, localFunOrder.getId()));
        if(CollectionUtils.isNotEmpty(localFunOrderRefunds)){
            List<LocalFunOrderRefund> collect = localFunOrderRefunds.stream().filter(entity -> entity.getActualRefundAmount() != null).collect(Collectors.toList());
            if(CollectionUtils.isNotEmpty(collect)){
                double sum = collect.stream().mapToDouble(entity -> entity.getActualRefundAmount().doubleValue()).sum();
                localFunOrderDetailDTO.setRefundedAmount(new BigDecimal(sum));
            }
        }

        setDic(localFunOrderDetailDTO);
        localFunOrderDetailDTO.setFlagStatus(localFunOrderDetailDTO.getPaymentStatus());
        return Result.success(localFunOrderDetailDTO);
    }

    private void setDic(LocalFunOrderDetailDTO localFunOrderDetailDTO) {
        if(localFunOrderDetailDTO.getSalesMethods() != null){
            localFunOrderDetailDTO.setSalesMethodsDesc(1== localFunOrderDetailDTO.getSalesMethods()?"单品销售":"打包销售");
        }
        if(localFunOrderDetailDTO.getPaymentStatus() != null){
            localFunOrderDetailDTO.setPaymentStatusDesc(OrderPaymentStatus.getOrderPaymentStatusName(localFunOrderDetailDTO.getPaymentStatus()));
        }
        if(localFunOrderDetailDTO.getScheduledStatus() != null){
            localFunOrderDetailDTO.setScheduledStatusDesc(OrderScheduledStatus.getOrderScheduledStatusName(localFunOrderDetailDTO.getScheduledStatus()));
        }
        //订单状态
        if (localFunOrderDetailDTO.getPaymentStatus() == null || OrderPaymentStatus.UN_PAYMENT.getCode().equals(localFunOrderDetailDTO.getPaymentStatus())) {
            localFunOrderDetailDTO.setOrderStatusDesc(OrderStatus.UN_PAYMENT.getName());
            localFunOrderDetailDTO.setOrderStatus(OrderStatus.UN_PAYMENT.getCode());
        } else if (OrderScheduledStatus.CONFIRM_RESERVE.getCode().equals(localFunOrderDetailDTO.getScheduledStatus())) {
            localFunOrderDetailDTO.setOrderStatusDesc(OrderStatus.CONFIRM_RESERVE.getName());
            localFunOrderDetailDTO.setOrderStatus(OrderStatus.CONFIRM_RESERVE.getCode());
        } else if (OrderScheduledStatus.RESERVE_SUCCESS.getCode().equals(localFunOrderDetailDTO.getScheduledStatus())) {
            localFunOrderDetailDTO.setOrderStatusDesc(OrderStatus.RESERVE_SUCCESS.getName());
            localFunOrderDetailDTO.setOrderStatus(OrderStatus.RESERVE_SUCCESS.getCode());
        } else if (OrderScheduledStatus.RESERVE_FAIL.getCode().equals(localFunOrderDetailDTO.getScheduledStatus())) {
            localFunOrderDetailDTO.setOrderStatusDesc(OrderStatus.RESERVE_FAIL.getName());
            localFunOrderDetailDTO.setOrderStatus(OrderStatus.RESERVE_FAIL.getCode());
        } else if (OrderPaymentStatus.ALREADY_CANCEL.getCode().equals(localFunOrderDetailDTO.getPaymentStatus())) {
            localFunOrderDetailDTO.setOrderStatusDesc(OrderStatus.ALREADY_CANCEL.getName());
            localFunOrderDetailDTO.setOrderStatus(OrderStatus.ALREADY_CANCEL.getCode());
        }
        if(localFunOrderDetailDTO.getCancelStatus() != null){
            localFunOrderDetailDTO.setCancelStatusDesc(ApprovalStatus.parseValue(localFunOrderDetailDTO.getCancelStatus()));
        }
        if(localFunOrderDetailDTO.getCancelStatus() != null && localFunOrderDetailDTO.getCancelStatus() == 0){
            localFunOrderDetailDTO.setCancelStatus(null);
        }
        if(localFunOrderDetailDTO.getProductType() != null){
           switch (localFunOrderDetailDTO.getProductType()){
               case 1:
                   localFunOrderDetailDTO.setProductTypeDesc("手动单");
                   break;
               case 2:
                   localFunOrderDetailDTO.setProductTypeDesc("自采");
                   break;
               case 3:
                   localFunOrderDetailDTO.setProductTypeDesc("API");
                   break;
               default:
                   break;
           }
        }
        if(localFunOrderDetailDTO.getSource() != null){
            localFunOrderDetailDTO.setSourceDesc(OrderSource.getOrderSourceName(localFunOrderDetailDTO.getSource()));
        }
    }

    @Override
    public Result localFunOrderCollection(LocalFunOrderCollectionDetailReq localFun0rderCollectionDetailReq, TokenUser user) {
        List<LocalFunOrderCollectionListReq> localFun0rderCollectionListReqList = localFun0rderCollectionDetailReq.getLocalFun0rderCollectionListReqList();
        if(CollectionUtils.isNotEmpty(localFun0rderCollectionListReqList)){
            for(LocalFunOrderCollectionListReq localFun0rderCollectionListReq : localFun0rderCollectionListReqList){
                CollectionAmountReq collectionAmountReq = localFun0rderCollectionListReq.getCollectionAmountReq();
                LocalFunOrderCollection localFunOrderCollection = new LocalFunOrderCollection();
                //生成收款单号,SKD+年後2位+月日4位+時分秒6位+2位隨機數字
                String collectionNumber = "SKD" + DateUtil.fmtNum(LocalDate.now()) + RandomUtil.randomNumbers(2);
                localFunOrderCollection = EntityUtil.copy(localFun0rderCollectionListReq, LocalFunOrderCollection.class);
                localFunOrderCollection.setCollectionNumber(collectionNumber);
                localFunOrderCollection.setCreateId(user.getId());
                localFunOrderCollection.setStatus(1);
                localFunOrderCollection.setIsPos(localFun0rderCollectionDetailReq.getPayWay());
                localFunOrderCollection.setOrderId(Long.parseLong(localFun0rderCollectionDetailReq.getOrderId()));
                localFunOrderCollection.setCurrencyId(collectionAmountReq.getCurrencyId());
                localFunOrderCollection.setCurrency(collectionAmountReq.getCurrency());
                localFunOrderCollection.setSalerId(user.getId());
                localFunOrderCollection.setSalerName(user.getUsername());
                localFunOrderCollection.setCollectionAmount(collectionAmountReq.getCollectionAmount());
                localFunOrderCollection.setGmtCreate(LocalDateTime.now());
                localFunOrderCollection.setId(SnowflakeIdWorker.nextId());
                localFunOrderCollectionMapper.insert(localFunOrderCollection);
            }
        }
        return Result.success();
    }

    @Override
    public Result<Long> cancelLocalFunOrder(LocalFun0rderCancelReq localFun0rderCancelReq, TokenUser tokenUser) {
        LocalFunOrder localFunOrder = localFunOrderMapper.selectById(localFun0rderCancelReq.getOrderId());
        localFunOrder.setPaymentStatus(OrderPaymentStatus.ALREADY_CANCEL.getCode());
        localFunOrder.setScheduledStatus(null);
        localFunOrder.setCancelStatus(null);
        localFunOrder.setModifiedId(tokenUser.getId());
        localFunOrder.setCancelReason(localFun0rderCancelReq.getCancelReason());
        localFunOrder.setGmtModified(LocalDateTime.now());
        localFunOrderMapper.updateById(localFunOrder);

        //3.还库存
        if(StringUtil.isNotEmpty(localFunOrder.getProductTicketsId())) {
            try {
                String[] attrIds = localFunOrder.getProductTicketsId().split(",");
                Long attrId1 = Long.valueOf(attrIds[0]);
                Long attrId2 = null;
                if (attrIds.length > 1) attrId2 = Long.valueOf(attrIds[1]);
                localFunProductSaleRecordService.backToStock(localFunOrder.getId(),localFunOrder.getProductId(),
                        attrId1,attrId2,localFunOrder.getTicketNum(),tokenUser.getId());
            } catch (NumberFormatException e) {
                log.error("B端待支付取消订单-还库存失败：{}",e.getMessage());
            }
        }


        return Result.success(Long.parseLong(localFun0rderCancelReq.getOrderId()));
    }

    @Transactional
    @Override
    public Result<Long> cancelLocalFunOrderRefund(LocalFunOrderRefundDetailReq localFun0rderRefundDetailReq, TokenUser tokenUser) {
        LocalFunOrder localFunOrder = localFunOrderMapper.selectById(localFun0rderRefundDetailReq.getOrderId());
        //审批状态 ，取消订单审批通过或正在审批中，不允许重复操作
        if(ApprovalStatus.REVIEWING.getCode().equals(localFunOrder.getCancelStatus()) ||
                ApprovalStatus.REVIEW_YES.getCode().equals(localFunOrder.getCancelStatus())){
            return Result.failed(SystemError.LOCAL_FUN_18013);
        }

//        if (localFunOrder.getPaymentStatus() == OrderPaymentStatus.ALREADY_PAYMENT.getCode() && localFunOrder.getScheduledStatus() == OrderScheduledStatus.RESERVE_SUCCESS.getCode()) {
//            // 已经付款，预订成功，不退不改
//            throw new BusinessException(SystemError.SHIP_PRODUCT_11030);
//        }
        //校验实际退款金额不能大于 订单金额-中途退改
        List<LocalFunOrderRefundListReq> reqList = localFun0rderRefundDetailReq.getLocalFun0rderRefundListReqList();
        if(CollectionUtils.isNotEmpty(reqList)){
            BigDecimal sums = new BigDecimal(0);
            List<BigDecimal> bigDecimals = reqList.stream().filter(en->en.getRefundAmountReq() != null).flatMap(en ->
                    Stream.of(en.getRefundAmountReq().getCollectionAmount())).collect(Collectors.toList());

            for(BigDecimal amount : bigDecimals){
                sums = sums.add(amount);
            }

            LocalFunProductOrderReq req = new LocalFunProductOrderReq();
            req.setId(localFunOrder.getId());
            Result<BigDecimal> refundAmount = getRefundAmount(req, null);
            if(sums.compareTo(refundAmount.getData()) > 0){
                return Result.failed(SystemError.LOCAL_FUN_18014);
            }
        }

        Result<ApprovalStartDTO> result = iSysApprovalService.start(SystemBusinessType.LOCAL_FUN.getCode(),
                SysApprovalType.CANCEL_LOCALFUN.getCode(),Long.parseLong(localFun0rderRefundDetailReq.getOrderId()),tokenUser.getId(),null,null);

        if(result.isSuccess()){
            //1.修改订单状态
            localFunOrder = EntityUtil.copy(localFun0rderRefundDetailReq, LocalFunOrder.class);
            localFunOrder.setCancelStatus(ApprovalStatus.REVIEWING.getCode());
            localFunOrder.setId(Long.valueOf(localFun0rderRefundDetailReq.getOrderId()));
            localFunOrder.setGmtModified(LocalDateTime.now());
            localFunOrder.setModifiedId(tokenUser.getId());
            localFunOrder.setCancelReason(localFun0rderRefundDetailReq.getCancelReason());
            localFunOrderMapper.updateById(localFunOrder);

            //2.记录退款记录
            String refundNumber= LocalFunOrderGenerator.getRefundNumber();
            saveOrderRefundRecord(localFun0rderRefundDetailReq, tokenUser,refundNumber);
        }else {
            Result result1 = new Result();
            result1.setCode(result.getCode());
            result1.setMsg(result.getMsg());
            return result1;
        }
        return Result.success(Long.valueOf(localFun0rderRefundDetailReq.getOrderId()));
    }

    /**
     * 退款认款申请
     * @param localFun0rderRefundDetailReq
     * @param localFunOrder
     * @param tokenUser
     * @param refundNumber
     */
    private void refundAmountApply(LocalFunOrderCheckReq localFun0rderRefundDetailReq, LocalFunOrder localFunOrder, TokenUser tokenUser, String refundNumber) {
        List<LocalRefundDTO> reqList = localFun0rderRefundDetailReq.getOrderRefundApprovalRecordReqList();
        if(CollectionUtils.isNotEmpty(reqList)){
            List<BillAddRefundReq> ars = reqList.stream().map(entity->{
                LocalFunOrderRefund localFunOrderRefund = localFunOrderRefundMapper.selectById(entity.getId());
                BillAddRefundReq req = new BillAddRefundReq();
                req.setBillNumber(localFunOrderRefund.getRefundNumber());
                req.setBusinessType(SystemBusinessType.LOCAL_FUN.getCode());
                req.setCollectionAmount(entity.getApprovalAmount());
                req.setCurrencyId(localFunOrderRefund.getCurrencyId());
                req.setCurrencyName(localFunOrderRefund.getCurrency());
                req.setSaleOrderId(localFunOrder.getId());
                req.setSaleOrderNumber(localFunOrder.getOrderNumber());
                req.setProductId(Lists.newArrayList(localFunOrder.getProductId()));
                req.setSaleUserId(localFunOrder.getSalesmanId());
                if(localFunOrder.getSalesmanId() != null){
                    UserDTO userDTO = iSysUserService.queryCacheUser(localFunOrder.getSalesmanId());
                    req.setSaleUserName(userDTO.getFullName());
                }
                req.setRefundTime(LocalDateTime.now());
                req.setRefundTypeId(localFunOrderRefund.getRefundWayId());
                req.setRefundType(localFunOrderRefund.getRefundWay());
                AccountJson json = new AccountJson();
                json.setCardNumber(localFunOrderRefund.getRefundAccount());
                req.setRefundAccountJson(json);
                //汇率
                BigDecimal exchangeRate = iMainDataCurrencyService.getMarketRateById(localFunOrderRefund.getCurrencyId());
                req.setExchangeRate(exchangeRate.doubleValue());

                //销售部门
                SysDepartmentDTO sysDepartmentDTO = iSysDepartmentService.queryByUserId(tokenUser.getId());
                if(sysDepartmentDTO != null){
                    req.setSaleDeptId(sysDepartmentDTO.getId());
                }

                Result<LocalFunResourceDetailDTO> result = iLocalFunResourceService.productDetail(localFunOrder.getProductId());
                if(result != null && result.getData() != null){
                    req.setProductName(result.getData().getName());
                    req.setProductNumber(result.getData().getProductCode());
                    req.setResourceInfo(Lists.newArrayList(result.getData().getFunName()));
                }

                return req;
            }).collect(Collectors.toList());


            iFinanceBillService.addRefund(ars);
        }
    }


    /**
     * 还库存
     * @param localFunOrder
     * @param payOrderReq
     * @param tokenUser
     */
    private void reBackRepository(LocalFunOrder localFunOrder, LocalFunOrderCheckReq payOrderReq, TokenUser tokenUser) {
        localFunProductSaleRecordService.backToStock(localFunOrder.getId(),localFunOrder.getProductId(),
                payOrderReq.getAttrId1(),payOrderReq.getAttrId2(),localFunOrder.getTicketNum(),tokenUser.getId());
    }

    /**
     * 记录退款记录
     * @param localFun0rderRefundDetailReq
     * @param tokenUser
     * @param refundNumber
     */
    private void saveOrderRefundRecord(LocalFunOrderRefundDetailReq localFun0rderRefundDetailReq, TokenUser tokenUser, String refundNumber) {
        List<LocalFunOrderRefundListReq> localFun0rderRefundListReqList = localFun0rderRefundDetailReq.getLocalFun0rderRefundListReqList();
        if(CollectionUtils.isNotEmpty(localFun0rderRefundListReqList)){
            for(LocalFunOrderRefundListReq visa0rderRefundListReq : localFun0rderRefundListReqList){
                LocalFunOrderRefund localFunOrderRefund = new LocalFunOrderRefund();
                localFunOrderRefund = EntityUtil.copy(visa0rderRefundListReq, LocalFunOrderRefund.class);
                LocalFunOrderRefundWayReq localFun0rderRefundWayReq = visa0rderRefundListReq.getLocalFun0rderRefundWayReq();
                localFunOrderRefund.setRefundWayId(Objects.isNull(localFun0rderRefundWayReq.getValue())?null:Long.parseLong(localFun0rderRefundWayReq.getValue()));
                localFunOrderRefund.setRefundWay(localFun0rderRefundWayReq.getLabel());
                localFunOrderRefund.setRefundNumber(refundNumber);
                localFunOrderRefund.setRefundReason(localFun0rderRefundDetailReq.getCancelReason());
                localFunOrderRefund.setId(SnowflakeIdWorker.nextId());
                localFunOrderRefund.setCreateId(tokenUser.getId());
                localFunOrderRefund.setStatus(ApprovalStatus.REVIEWING.getCode());
                localFunOrderRefund.setOrderId(Long.valueOf(localFun0rderRefundDetailReq.getOrderId()));
                RefundAmountReq refundAmountReq = visa0rderRefundListReq.getRefundAmountReq();
                localFunOrderRefund.setCurrencyId(refundAmountReq.getCurrencyId());
                localFunOrderRefund.setCurrency(refundAmountReq.getCurrency());
                localFunOrderRefund.setRefundAmount(refundAmountReq.getCollectionAmount());
                localFunOrderRefundMapper.insert(localFunOrderRefund);
            }
        }
    }

    @Override
    public Result<Long> confirmOrder(LocalFunProductOrderReq localFunProductOrderReq,TokenUser tokenUser) {
        LocalFunOrder localFunOrder = localFunOrderMapper.selectById(localFunProductOrderReq.getOrderId());
        localFunOrder.setFileJson(localFunProductOrderReq.getFileJson());
        localFunOrder.setScheduledStatus(OrderScheduledStatus.RESERVE_SUCCESS.getCode());
        localFunOrderMapper.updateById(localFunOrder);

        //确认预订
        SupplierOrderSystemFreeCallConfirmReq callConfirmReq = new SupplierOrderSystemFreeCallConfirmReq();
        callConfirmReq.setSaleNumber(localFunOrder.getOrderNumber());
        callConfirmReq.setFilesJson(localFunOrder.getFileJson());
        callConfirmReq.setSupplierOrderNumber(localFunProductOrderReq.getSupplierOrder());
        iSupplierOrderService.freeCallSystemConfirm(callConfirmReq,tokenUser.getId());
        return Result.success(localFunOrder.getId());
    }

    @Override
    public Result notice(LocalFunOrderNoticeReq localFun0rderNoticeReq) {
//        MailUtil.sendSimpleTextMail("1204920594@qq.com","","333");
        return Result.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Integer> updateOrderConfirmStatus(Long orderId,Integer reservationStatus) {
        UpdateWrapper<LocalFunOrder> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda().set(LocalFunOrder::getScheduledStatus,reservationStatus);

        //预定成功
        if(OrderScheduledStatus.RESERVE_SUCCESS.getCode().equals(reservationStatus)){
            DynamicAffirmOrderReq dynamicAffirmOrderReq = new DynamicAffirmOrderReq();
            dynamicAffirmOrderReq.setOrderId(orderId);
            dynamicAffirmOrderReq.setProductFlag("7");
            dynamicAffirmOrderReq.setScheduledStatus(reservationStatus);
            iSeasonOrderService.affirmDynamicOrder(dynamicAffirmOrderReq);
        }

        //预定取消
        if(OrderScheduledStatus.RESERVE_FAIL.getCode().equals(reservationStatus)){
            CancelStatusReq cancelStatusReq = new CancelStatusReq();
            cancelStatusReq.setOrderId(orderId);
            cancelStatusReq.setProductFlag("7");
            cancelStatusReq.setCancelStatus(reservationStatus);
            iSeasonOrderService.cancelOrderStatus(cancelStatusReq);
        }
        return Result.success(localFunOrderMapper.update(null,updateWrapper));
    }

    @Override
    public Result<Long> updateOrderPaymentStatus(Long orderId) {
        LocalFunOrder localFunOrder = localFunOrderMapper.selectById(orderId);
        if(localFunOrder == null){
            return Result.failed(SystemError.LOCAL_FUN_18010);
        }
        if(OrderPaymentStatus.UN_PAYMENT.getCode().equals(localFunOrder.getPaymentStatus())){
            localFunOrder.setPaymentStatus(OrderPaymentStatus.ALREADY_CANCEL.getCode());
            localFunOrder.setScheduledStatus(null);
            localFunOrder.setGmtModified(LocalDateTime.now());
            localFunOrderMapper.updateById(localFunOrder);
        }
        return Result.success(orderId);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result<Long> payOrder(LocalFunDyTicketPayOrderReq req) {
        //生成订单ID
        long orderId = SnowflakeIdWorker.nextId();
        LocalFunOrderInfo localFunOrderInfo = new LocalFunOrderInfo();
        //1.保存订单信息
        LocalFunOrder localFunOrder = saveOrderInfo(req.getLocalFunAddCheckOrderReq().getLocalFunOrderInputCheckReq(), req.getTokenUser(), orderId,2, localFunOrderInfo);
        LocalFunOrderInputCheckReq req1 = req.getLocalFunAddCheckOrderReq().getLocalFunOrderInputCheckReq();
        //2.登记旅客资料
        registerTouristInfo(req.getLocalFunAddCheckOrderReq().getTouristInfos(),req.getTokenUser().getId(),orderId,req1.getAttr1Id(),req1.getAttr2Id(),req1.getProductId(), localFunOrderInfo);

        //订单信息
        LocalFunPayOrderCollectionReq collectionReq = req.getPayOrderReq().getReqList().stream().findFirst().orElse(null);
        if(collectionReq != null){
            collectionReq.setOrderId(orderId);
        }

        //3.收款前订单校验
        Result checkResult = checkOrderBeforePay(req.getPayOrderReq().getReqList(), collectionReq);
        if (checkResult != null) return checkResult;

        //4.记录收款细节
        createOrderCollection(req.getPayOrderReq().getReqList(), req.getTokenUser(), collectionReq);

        //5.记录收款凭据
        LocalFunOrderReceiptAddReq reqReceipt = new LocalFunOrderReceiptAddReq();
        reqReceipt.setOrderId(orderId);
        iLocalFunOrderReceiptService.add(reqReceipt,req.getTokenUser());
        Result<LocalFunResourceDetailDTO> result = iLocalFunResourceService.productDetail(localFunOrder.getProductId());

        //6.生成供应预订单
        callSupplierOrder(req.getTokenUser(),orderId,localFunOrder, result);

        //7.修改订单状态，返回产品信息
        Result<LocalFunResourceDetailDTO> dtoResult = updateOrderStatus(collectionReq, localFunOrder, collectionReq, result, req.getTokenUser(), req.getPayOrderReq().getReqList());

        //8.扣减库存
        // 1 自营 2代理商
        Integer channel = localFunOrder.getIsAgent() == null || !new Integer(2).equals(localFunOrder.getIsAgent()) ? 1 : 2;
        CustomDto customSelLine = iLocalFunProductService.getCustomSelLine(localFunOrder.getProductId(), channel, req.getTokenUser().getId(), localFunOrder.getAgencyId());
        localFunProductSaleRecordService.operateStock(LocalFunStockReq.builder().attrId1(req.getPayOrderReq().getAttrId1())
                .attrId2(req.getPayOrderReq().getAttrId2())
                .num(localFunOrder.getTicketNum())
                .userId(req.getTokenUser().getId()).productId(localFunOrder.getProductId()).orderId(collectionReq.getOrderId())
                //线下
                .line(1)
                .channel(channel)
                .checkType(Objects.isNull(customSelLine)?null:customSelLine.getCheckType())
                .customId(Objects.isNull(customSelLine)?null:customSelLine.getCustomId())
                .customName(Objects.isNull(customSelLine)?null:customSelLine.getCustomName()).build());

        //9.认款申请
        iFinanceBillService.addCollection(obtainCollectionApply(localFunOrder,req.getPayOrderReq().getReqList(),dtoResult,req.getTokenUser()));

        return Result.success(orderId);
    }

    @Override
    public Result<Long> payFixOrder(LocalFunFixTicketPayOrderReq req) {
        //生成订单ID
        long orderId = SnowflakeIdWorker.nextId();
        //产品信息
        Result<LocalFunResourceDetailDTO> result = iLocalFunResourceService.productDetail(req.getProductId());
        LocalFunResourceDetailDTO productInfo = result.getData();
        //1.保存订单信息
        LocalFunOrder localFunOrder = saveFixOrderInfo(req, productInfo,orderId);

        //订单信息
        LocalFunPayOrderCollectionReq collectionReq = req.getReqList().stream().findFirst().orElse(null);
        if(collectionReq != null){
            collectionReq.setOrderId(orderId);
        }

        //3.收款前订单校验
        Result checkResult = checkOrderBeforePay(req.getReqList(), collectionReq);
        if (checkResult != null) return checkResult;

        //4.记录收款细节
        createOrderCollection(req.getReqList(), req.getTokenUser(), collectionReq);

        //5.记录收款凭据
        LocalFunOrderReceiptAddReq reqReceipt = new LocalFunOrderReceiptAddReq();
        reqReceipt.setOrderId(orderId);
        iLocalFunOrderReceiptService.add(reqReceipt,req.getTokenUser());

        //6.挂账 代理下单
        callFinanceOnAccount(req.getReqList(),localFunOrder,req.getTokenUser(),result);

        //7.生成供应预订单
        //套票下订单，如果是内部挂账，套票负责人部门和产品负责人部门，不是同一个部门则创建2个供应商预定单
        callTicketSupplier(req,localFunOrder,productInfo);

        //8.修改订单状态，返回产品信息
        updateOrderStatus(collectionReq, localFunOrder, collectionReq, result, req.getTokenUser(), req.getReqList());

        //9.扣减库存
        // 1 自营 2代理商
        Integer channel = localFunOrder.getIsAgent() == null || !new Integer(2).equals(localFunOrder.getIsAgent()) ? 1 : 2;
        CustomDto customSelLine = iLocalFunProductService.getCustomSelLine(localFunOrder.getProductId(), channel, req.getTokenUser().getId(), localFunOrder.getAgencyId());
        localFunProductSaleRecordService.operateStock(LocalFunStockReq.builder().attrId1(req.getAttrId1())
                .attrId2(req.getAttrId2())
                .num(localFunOrder.getTicketNum())
                .userId(req.getTokenUser().getId()).productId(localFunOrder.getProductId()).orderId(collectionReq.getOrderId())
                //线下
                .line(1)
                .channel(channel)
                .checkType(Objects.isNull(customSelLine)?null:customSelLine.getCheckType())
                .customId(Objects.isNull(customSelLine)?null:customSelLine.getCustomId())
                .customName(Objects.isNull(customSelLine)?null:customSelLine.getCustomName()).build());

        return Result.success(orderId);
    }

    @Override
    public Result<QueryQuotaDTO> queryQuota(QueryQuotaReq req) {
        LocalFunOrder localFunOrder = localFunOrderMapper.selectById(req.getOrderId());
        com.ctshk.rpc.finance.req.onaccount.QueryQuotaReq queryQuotaReq = new com.ctshk.rpc.finance.req.onaccount.QueryQuotaReq();
        queryQuotaReq.setAccountId(localFunOrder.getAgencyId());
        queryQuotaReq.setCurrencyId(req.getCurrencyId());
        Result<com.ctshk.rpc.finance.dto.onaccount.QueryQuotaDTO> queryQuotaDTOResult = onAccountCurrencyQuotaService.queryQuota(queryQuotaReq);
        if (queryQuotaDTOResult.getCode() != 0){
            throw new BusinessException(SystemError.LOCAL_FUN_18008, queryQuotaDTOResult.getMsg());
        }
        com.ctshk.rpc.finance.dto.onaccount.QueryQuotaDTO data = queryQuotaDTOResult.getData();
        QueryQuotaDTO queryQuotaDTO = EntityUtil.copy(data, QueryQuotaDTO.class);
        return Result.success(queryQuotaDTO);
    }

    @Override
    @Transactional
    public Result<Long> refundOperate(LocalFunOrderCheckReq localFunProductCheckReq, TokenUser currentUser) {
        //校验
        List<LocalRefundDTO> reqList = localFunProductCheckReq.getOrderRefundApprovalRecordReqList();
        if(CollectionUtils.isEmpty(reqList)){
            return Result.failed(SystemError.LOCAL_FUN_18020);
        }
        BigDecimal sums = new BigDecimal(0);
        List<BigDecimal> bigDecimals = reqList.stream().filter(en->en.getApprovalAmount() != null).flatMap(en ->
                Stream.of(en.getApprovalAmount())).collect(Collectors.toList());

        for(BigDecimal amount : bigDecimals){
            sums = sums.add(amount);
        }
        LocalFunProductOrderReq req = new LocalFunProductOrderReq();
        req.setId(localFunProductCheckReq.getBusinessId());
        Result<BigDecimal> refundAmount = getRefundAmount(req, null);
        if(sums.compareTo(refundAmount.getData()) > 0){
            return Result.failed(SystemError.LOCAL_FUN_18014);
        }

        Result<ApprovalCheckDTO> result = iSysApprovalService.check(localFunProductCheckReq.getApprovalId(),currentUser.getId(),localFunProductCheckReq.getApprovalStatus(),localFunProductCheckReq.getComments());
        if(result.isSuccess()){
            if(result.getData().getIsFinish()){
                LocalFunOrder localFunOrder = localFunOrderMapper.selectById(localFunProductCheckReq.getBusinessId());
                if(localFunOrder == null){
                    return Result.failed(SystemError.LOCAL_FUN_18010);
                }
                localFunOrder.setGmtModified(LocalDateTime.now());
                localFunOrder.setModifiedId(currentUser.getId());
                localFunOrder.setCancelStatus(localFunProductCheckReq.getApprovalStatus());
                localFunOrder.setScheduledStatus(null);
                localFunOrder.setRefundApproveDate(LocalDateTime.now());
                localFunOrder.setPaymentStatus(OrderPaymentStatus.ALREADY_CANCEL.getCode());
                localFunOrderMapper.updateById(localFunOrder);

                String refundNumber= LocalFunOrderGenerator.getRefundNumber();

                if(localFunProductCheckReq.getApprovalStatus() == 4){
                    UpdateWrapper<LocalFunOrderRefund> updateWrapper = new UpdateWrapper<>();
                    updateWrapper.lambda().eq(LocalFunOrderRefund::getOrderId, localFunOrder.getId());
                    updateWrapper.lambda().set(LocalFunOrderRefund::getStatus,localFunProductCheckReq.getApprovalStatus());
                    localFunOrderRefundMapper.update(null,updateWrapper);
                }
                if(localFunProductCheckReq.getApprovalStatus() == 3){
                    //校验实际退款金额不能大于 订单金额
                    if(CollectionUtils.isNotEmpty(reqList)){
                        for(LocalRefundDTO dto : reqList){
                            if(dto.getId() == null){
                                return Result.failed(SystemError.LOCAL_FUN_18025);
                            }
                            UpdateWrapper<LocalFunOrderRefund> updateWrapper = new UpdateWrapper<>();
                            updateWrapper.lambda().eq(LocalFunOrderRefund::getId, dto.getId());
                            updateWrapper.lambda().set(LocalFunOrderRefund::getActualRefundAmount,dto.getApprovalAmount());
                            updateWrapper.lambda().set(LocalFunOrderRefund::getGmtModified,LocalDateTime.now());
                            localFunOrderRefundMapper.update(null,updateWrapper);
                        }
                    }
                    //2.更新退款审批状态
                    updateRefundStatus(localFunOrder,localFunProductCheckReq);
                    //3.还库存
                    reBackRepository(localFunOrder,localFunProductCheckReq,currentUser);

                    //4.退款认款申请
                    refundAmountApply(localFunProductCheckReq,localFunOrder,currentUser,refundNumber);

                    //5.回滚挂账额度
                    List<LocalFunOrderCollection> quotaList = localFunOrderCollectionMapper.selectList(Wrappers.<LocalFunOrderCollection>
                            lambdaQuery().eq(LocalFunOrderCollection::getOrderId, localFunOrder.getId())
                            .eq(LocalFunOrderCollection::getCollectionWay, "掛賬"));
                    if(CollectionUtils.isNotEmpty(quotaList)){
                        for(LocalFunOrderCollection collection : quotaList){
                            RollBackQuotaReq rollBackQuotaReq = new RollBackQuotaReq();
                            rollBackQuotaReq.setAmount(collection.getCollectionAmount());
                            rollBackQuotaReq.setCollectionNumber(collection.getCollectionNumber());
                            rollBackQuotaReq.setOrderId(localFunOrder.getId());
                            rollBackQuotaReq.setUserId(currentUser.getId());
                            rollBackQuotaReq.setBusinessType(SystemBusinessType.LOCAL_FUN.getCode());
                            onAccountCurrencyQuotaService.rollBackQuota(rollBackQuotaReq);
                        }
                    }
                }
            }
        }else {
            Result result1 = new Result();
            result1.setCode(result.getCode());
            result1.setMsg(result.getMsg());
            return result1;
        }
        return Result.success(localFunProductCheckReq.getApprovalId());
    }


    /**
     * 更新退款状态
     * @param localFunOrder
     * @param localFunProductCheckReq
     */
    private void updateRefundStatus(LocalFunOrder localFunOrder, LocalFunOrderCheckReq localFunProductCheckReq) {
        List<LocalRefundDTO> orderRefundApprovalRecordReqList = localFunProductCheckReq.getOrderRefundApprovalRecordReqList();
        if(CollectionUtils.isNotEmpty(orderRefundApprovalRecordReqList)){
            orderRefundApprovalRecordReqList.forEach(entity->{
                UpdateWrapper<LocalFunOrderRefund> updateWrapper = new UpdateWrapper<>();
                updateWrapper.lambda().eq(LocalFunOrderRefund::getId, entity.getId());
                updateWrapper.lambda().set(LocalFunOrderRefund::getActualRefundAmount,entity.getApprovalAmount());
                updateWrapper.lambda().set(LocalFunOrderRefund::getStatus,localFunProductCheckReq.getApprovalStatus());
                localFunOrderRefundMapper.update(null,updateWrapper);
            });
        }
    }

    @Override
    public Result supplierConfirmOrder(SystemConfirmReq systemConfirmReq, Long userId) {
        QueryWrapper<LocalFunOrder> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(LocalFunOrder::getOrderNumber, systemConfirmReq.getSaleNumber());
        LocalFunOrder localFunOrder = localFunOrderMapper.selectOne(wrapper);
        if(localFunOrder == null){
            throw new BusinessException(SystemError.LOCAL_FUN_18010);
        }
        localFunOrder.setScheduledStatus(systemConfirmReq.getReserveStatus());
        localFunOrderMapper.updateById(localFunOrder);
        return Result.success(localFunOrder.getId());
    }

    @Override
    public Result<BigDecimal> getOrderAmount(LocalFunProductOrderReq localFunOrderCheckReq, TokenUser currentUser) {
        LocalFunOrder localFunOrder = localFunOrderMapper.selectById(localFunOrderCheckReq.getId());
        if(localFunOrder == null){
            return Result.failed(SystemError.LOCAL_FUN_18010);
        }
        return Result.success(localFunOrder.getReceivableAmount());
    }

    @Override
    public Result<List<MyLocalFunOrderDTO>> recentToNow(LocalDateTime recent, LocalDateTime now) {
        List<LocalFunOrder> orderList = baseMapper.selectList(Wrappers.<LocalFunOrder>lambdaQuery()
                .eq(LocalFunOrder::getIsDeleted,IsDeletedCode.NO.getCode())
                .ge(recent != null,LocalFunOrder::getGmtModified, recent)
                .le(LocalFunOrder::getGmtModified, now));

        List<MyLocalFunOrderDTO> result = new ArrayList<>();

        for (LocalFunOrder localFunOrder : orderList) {
            MyLocalFunOrderDTO orderDTO = EntityUtil.copy(localFunOrder, MyLocalFunOrderDTO.class);
            LocalFunProductDetailReq req = new LocalFunProductDetailReq();
            req.setId(orderDTO.getProductId());
            Result<LocalFunProductDetailByIdDTO> localFunProductDetailByIdDTOResult = iLocalFunProductService.localFunProductDetailByIdDTO(req);
            if(localFunProductDetailByIdDTOResult.isSuccess()) {
                LocalFunProductDetailByIdDTO data = localFunProductDetailByIdDTOResult.getData();
                if(Objects.equals(data.getVaildType(), 1)) {
                    Double vaildDay = data.getVaildDay();
                    LocalDateTime gmtCreate = orderDTO.getGmtCreate();
                    orderDTO.setVaildDayBegin(gmtCreate);
                    orderDTO.setVaildDayEnd(gmtCreate.plusDays(vaildDay.longValue()));
                    orderDTO.setProductName(data.getName());
                } else if(Objects.equals(data.getVaildType(), 2)){
                    orderDTO.setVaildDayBegin(data.getVaildDayBegin());
                    orderDTO.setVaildDayEnd(data.getVaildDayEnd());
                    orderDTO.setProductName(data.getName());
                }
                orderDTO.setVaildDayBegin(data.getVaildDayBegin());
                orderDTO.setVaildDayEnd(data.getVaildDayEnd());
            }
            result.add(orderDTO);
        }
        return Result.success(result);
    }

    @Override
    public List<AddIntegralLocalFunOrderDTO> queryOrderDTOList(LocalDateTime start, LocalDateTime end) {
        return EntityUtil.copyList(baseMapper.selectList(Wrappers.<LocalFunOrder>lambdaQuery()
                .eq(LocalFunOrder::getIsDeleted, IsDeletedCode.NO.getCode())
                .ge(LocalFunOrder::getGmtCreate, start)
                .le(LocalFunOrder::getGmtCreate, end)),AddIntegralLocalFunOrderDTO.class);
    }

    @Override
    public Result<BigDecimal> getRefundAmount(LocalFunProductOrderReq localFunOrderCheckReq, TokenUser currentUser) {
        LocalFunOrder localFunOrder = localFunOrderMapper.selectById(localFunOrderCheckReq.getId());
        if(localFunOrder == null){
            throw new BusinessException(SystemError.LOCAL_FUN_18010);
        }

        Result<LocalFunResourceDetailDTO> result = iLocalFunResourceService.productDetail(localFunOrder.getProductId());
        if(result != null && result.getData() != null){
            if(result.getData().getCtsChargeType() == null){
                return Result.success(localFunOrder.getReceivableAmount());
            }
            //数值
            if(result.getData().getCtsChargeType() == 1){
                return Result.success(localFunOrder.getReceivableAmount().subtract(result.getData().getCtsCharge()));
            }else if(result.getData().getCtsChargeType() == 2){
                //获取规格信息
                try {
                    String productTicketsId = localFunOrder.getProductTicketsId();
                    String[] split = productTicketsId.split(",");
                    Long attrId1 = null;
                    Long attrId2 = null;
                    if(split.length > 0){
                        attrId1 = Long.valueOf(split[0]);
                    }
                    if(split.length == 2 && !"null".equals(split[1])){
                        attrId2 = Long.valueOf(split[1]);
                    }
                    LocalFunStockInfo costTouristStockInfo = iLocalFunAppProductService.getCostTouristStockInfo(attrId1, attrId2);
                    if(costTouristStockInfo != null){
                        return Result.success(localFunOrder.getReceivableAmount().subtract(costTouristStockInfo.getCostPrice().multiply(new BigDecimal(0.01)).multiply(result.getData().getCtsCharge())));
                    }
                } catch (NumberFormatException e) {
                    log.error("获取规格信息失败");
                }
            }
        }
        return Result.success(localFunOrder.getReceivableAmount());
    }


    /**
     * 套票下供应商预定单
     * @param req
     * @param localFunOrder
     * @param productInfo
     */
    private void callTicketSupplier(LocalFunFixTicketPayOrderReq req, LocalFunOrder localFunOrder, LocalFunResourceDetailDTO productInfo) {
        List<LocalFunPayOrderCollectionReq> reqList = req.getReqList();
        boolean isInternalAccount = reqList.stream().anyMatch(entity -> PayRefundMethod.NAC.getId().equals(entity.getCollectionWayId()));
        //内部挂账
        if(isInternalAccount){
            // 生成供应预订单
            SupplierOrderSystemLocalFunAddReq supplierOrderSystemAirExpressAddReq = new SupplierOrderSystemLocalFunAddReq();
            supplierOrderSystemAirExpressAddReq.setOrderType(1);
            supplierOrderSystemAirExpressAddReq.setSupplierOrderType("2");
            supplierOrderSystemAirExpressAddReq.setBusinessType(SystemBusinessType.LOCAL_FUN.getCode());
            supplierOrderSystemAirExpressAddReq.setTotalFee(localFunOrder.getOrderAmount());
            supplierOrderSystemAirExpressAddReq.setPayableAmount(localFunOrder.getReceivableAmount());
            supplierOrderSystemAirExpressAddReq.setSaleNumber(localFunOrder.getOrderNumber());
            supplierOrderSystemAirExpressAddReq.setConfirmStatus(localFunOrder.getScheduledStatus());

            MainDataCurrencyQueryDTO currencyEntity = iMainDataCurrencyService.getExchangeCurrencyEntity("HKD", CurrencyRateExchangeConstant.MARKET_EXCHANGE_RATE_);
            supplierOrderSystemAirExpressAddReq.setCurrencyId(currencyEntity.getId());
            supplierOrderSystemAirExpressAddReq.setCurrency("HKD");

            Result<LocalFunResourceDetailDTO> result = iLocalFunResourceService.productDetail(localFunOrder.getProductId());
            if(result.getData() != null){
                LocalFunResourceDetailDTO detailDTO = result.getData();
                supplierOrderSystemAirExpressAddReq.setProductNumber(detailDTO.getProductCode());
                supplierOrderSystemAirExpressAddReq.setProductName(detailDTO.getName());
                supplierOrderSystemAirExpressAddReq.setSupplierId(detailDTO.getSupplierId());
                supplierOrderSystemAirExpressAddReq.setSupplierName(detailDTO.getSupplierName());
                supplierOrderSystemAirExpressAddReq.setProductType(detailDTO.getSourceType());
            }
            supplierOrderSystemAirExpressAddReq.setSupplierSystemOrderLocalFunAddReqList(createLocalFunData(result,localFunOrder,req.getTokenUser()));

            //产品负责人 产品资源部门
            UserDTO userDTO = iSysUserService.loadUserByParam(productInfo.getChargeUserId(), 1);
            SysDepartmentDTO sysDepartmentDTO = iSysDepartmentService.queryOne(userDTO.getDeptId());

            //当前负责人 产品资源部门
            UserDTO userDTO2 = iSysUserService.loadUserByParam(req.getChargeUserId(), 1);
            SysDepartmentDTO sysDepartmentDTO2 = iSysDepartmentService.queryOne(userDTO2.getDeptId());


            //产品资源负责人和套票负责人在同一个部门，仅生产一条供应商预定单
            if(sysDepartmentDTO.getId().equals(sysDepartmentDTO2.getId())){
                supplierOrderSystemAirExpressAddReq.setDepartmentId(userDTO.getDeptId());
                supplierOrderSystemAirExpressAddReq.setDepartment(sysDepartmentDTO.getTitle());
                iSupplierOrderService.addSystemLocalFun(supplierOrderSystemAirExpressAddReq, req.getTokenUser().getId());
            }else {
                supplierOrderSystemAirExpressAddReq.setDepartmentId(userDTO.getDeptId());
                supplierOrderSystemAirExpressAddReq.setDepartment(sysDepartmentDTO.getTitle());
                iSupplierOrderService.addSystemLocalFun(supplierOrderSystemAirExpressAddReq, req.getTokenUser().getId());

                supplierOrderSystemAirExpressAddReq.setDepartmentId(userDTO2.getDeptId());
                supplierOrderSystemAirExpressAddReq.setDepartment(sysDepartmentDTO2.getTitle());
                iSupplierOrderService.addSystemLocalFun(supplierOrderSystemAirExpressAddReq, req.getTokenUser().getId());
            }

        }else {
            Result<LocalFunResourceDetailDTO> result = iLocalFunResourceService.productDetail(localFunOrder.getProductId());
            callSupplierOrder(req.getTokenUser(),localFunOrder.getId(),localFunOrder, result);
        }

    }


    /**
     * 固定套票下订单
     * @param req
     * @param productInfo
     * @param orderId
     * @return
     */
    private LocalFunOrder saveFixOrderInfo(LocalFunFixTicketPayOrderReq req, LocalFunResourceDetailDTO productInfo, long orderId) {

        UserDTO user = iSysUserService.loadUserByParam(req.getTokenUser().getId(), 1);
        SysDepartmentDTO sysDepartmentDTO =  iSysDepartmentService.queryByUserId(req.getTokenUser().getId());
        LocalFunOrder localFunOrder = new LocalFunOrder();
        //1.设置服务费(单服务费*门票数)
        if(productInfo!= null){
            localFunOrder.setServiceFee(getServiceFee(productInfo.getReserveCharge(),1));
        }
        //2.设置门票总额(单张门票价格*门票数)
        localFunOrder.setTicketsFee(getTicketsFee(req.getSingleTicketAmount(),1));
        //3.设置订单总额 = 门票价格+服务费
        localFunOrder.setReceivableAmount(localFunOrder.getServiceFee().add(localFunOrder.getTicketsFee()));
        //4.设置规格ID
        localFunOrder.setProductTicketsId(req.getAttrId1()+","+req.getAttrId2());
        localFunOrder.setUseDate(LocalDateTime.now());
        localFunOrder.setTicketNum(1);
        LocalDateTime createTime = LocalDateTime.now();
        localFunOrder.setId(orderId);
        localFunOrder.setCreateId(req.getTokenUser().getId());
        localFunOrder.setOrderNumber(LocalFunOrderGenerator.getOrderNumer(sysDepartmentDTO.getDeptCode(),user.getEmployeeNumber()));
        localFunOrder.setPaymentStatus(OrderPaymentStatus.UN_PAYMENT.getCode());
        localFunOrder.setCancelStatus(NumberConstant.ZERO.getValue());
        localFunOrder.setScheduledStatus(OrderScheduledStatus.CONFIRM_RESERVE.getCode());
        localFunOrder.setSource(OrderSource.CPM.getCode());
        localFunOrder.setSalesmanId(user.getId());
        localFunOrder.setSalesmanName(user.getUsername());
        //销售方式(1：单品销售 2：打包销售)
        localFunOrder.setSalesMethods(2);
        localFunOrder.setProductType(1);//产品类型(1手工单，2外挂单)
        /**最晚付款时间为创建订单后15分钟*/
        localFunOrder.setPayExpireDate(createTime.plusMinutes(15));
        localFunOrder.setGmtCreate(createTime);
        localFunOrder.setGmtModified(createTime);
        //3.设置订单总额 = 应收总额 - 积分折扣 - 优惠折扣
        LocalFunOrderInputCheckReq req1 = new LocalFunOrderInputCheckReq();
        //套票没有积分优惠等
        localFunOrder.setOrderAmount(localFunOrder.getServiceFee().add(localFunOrder.getTicketsFee()));

        Result<LocalFunResourceDetailDTO> result = iLocalFunResourceService.productDetail(req.getProductId());
        if(result.getData() != null){
            LocalFunResourceDetailDTO detail = result.getData();
            localFunOrder.setProductCityId(detail.getCityId());
            localFunOrder.setProductCityName(detail.getCityName());
            localFunOrder.setProductFunType(detail.getFunType());
            localFunOrder.setProductFunName(detail.getFunName());
            localFunOrder.setProductName(detail.getName());
        }
        localFunOrderMapper.insert(localFunOrder);

        return localFunOrder;
    }

    /**
     * 根据币种名称获取汇率
     *
     * @param currencySy
     * @return
     */
    private BigDecimal getCrmExchangeRateByName(String currencySy) {
        List<MainDataCurrencyQueryDTO> list = iMainDataCurrencyService.queryList(Lists.newArrayList(Long.valueOf(currencySy)));

        if (com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isEmpty(list)) {
            throw new BusinessException(SystemError.AIREXPRESS_ORDER_60003);
        }
        MainDataCurrencyQueryDTO currencyQueryDTO = list.stream().findFirst().orElse(null);
        if(currencyQueryDTO == null){
            throw new BusinessException(SystemError.AIREXPRESS_ORDER_60003);
        }
        return currencyQueryDTO.getCrmExchangeRate();
    }


    /**
     * 保存订单信息
     * @param localFunOrderInputCheckReq    入参订单信息
     * @param tokenUser                        用户ID
     * @param orderId                       订单ID
     * @param isPackage
     * @param localFunOrderInfo
     */
    private LocalFunOrder saveOrderInfo(LocalFunOrderInputCheckReq localFunOrderInputCheckReq, TokenUser tokenUser, long orderId, int isPackage, LocalFunOrderInfo localFunOrderInfo) {
        Integer strategyType = localFunOrderInputCheckReq.getIsAgent() == null || !new Integer(2).equals(localFunOrderInputCheckReq.getIsAgent()) ? 1 : 2;
        Long relId =  localFunOrderInputCheckReq.getIsAgent() == null || !new Integer(2).equals(localFunOrderInputCheckReq.getIsAgent()) ? tokenUser.getId() : localFunOrderInputCheckReq.getAgencyId();

        LocalFunPriceRemainderDTO localFunSalePriceInfoHandle = iLocalFunProductService
                .findLocalFunSalePriceInfoHandle(strategyType, localFunOrderInputCheckReq.getProductId(), LocalDate.now(), relId, localFunOrderInputCheckReq.getAttr1Id(), localFunOrderInputCheckReq.getAttr2Id());

        log.info("获取票价信息：{}",JSON.toJSONString(localFunSalePriceInfoHandle));
        //单张票价
        BigDecimal singlePrice = localFunSalePriceInfoHandle.getPrice();
        //单张服务费
        BigDecimal chargePrice = localFunSalePriceInfoHandle.getReserveCharge();

        UserDTO user = iSysUserService.loadUserByParam(tokenUser.getId(), 1);
        SysDepartmentDTO sysDepartmentDTO =  iSysDepartmentService.queryByUserId(tokenUser.getId());

        /**
         * 应收总额：门票单价*票数+服务费
         * 订单总额：应收总额 = 积分折扣 - 优惠折扣
         */
        LocalFunOrder localFunOrder = EntityUtil.copy(localFunOrderInputCheckReq, LocalFunOrder.class);
        localFunOrderInfo.setSinglePrice(singlePrice);
        localFunOrderInfo.setChargePrice(chargePrice);
        //1.设置服务费(单服务费*门票数)
        localFunOrder.setServiceFee(getServiceFee(chargePrice,localFunOrderInputCheckReq.getServiceNum()));
        //2.设置门票总额(单张门票价格*门票数)
        localFunOrder.setTicketsFee(getTicketsFee(singlePrice,localFunOrderInputCheckReq.getNum()));
        //应收总额
        localFunOrder.setOrderAmount(localFunOrder.getServiceFee().add(localFunOrder.getTicketsFee()));

        //4.设置规格ID
        localFunOrder.setProductTicketsId(localFunOrderInputCheckReq.getAttr1Id()+","+localFunOrderInputCheckReq.getAttr2Id());
        localFunOrder.setUseDate(DateUtil.toLocalDateTime(localFunOrderInputCheckReq.getUseDate()));
        localFunOrder.setTicketNum(localFunOrderInputCheckReq.getNum());
        LocalDateTime createTime = LocalDateTime.now();
        localFunOrder.setId(orderId);
        localFunOrder.setCreateId(tokenUser.getId());
        localFunOrder.setOrderNumber(LocalFunOrderGenerator.getOrderNumer(sysDepartmentDTO.getDeptCode(),user.getEmployeeNumber()));
        localFunOrder.setPaymentStatus(OrderPaymentStatus.UN_PAYMENT.getCode());
        localFunOrder.setSource(OrderSource.CPM.getCode());
        localFunOrder.setSalesmanId(user.getId());
        localFunOrder.setSalesmanName(user.getUsername());
        //销售方式(1：单品销售 2：打包销售)
        localFunOrder.setSalesMethods(isPackage);
        localFunOrder.setProductType(1);//产品类型(1手工单，2外挂单)
        /**最晚付款时间为创建订单后15分钟*/
        localFunOrder.setPayExpireDate(createTime.plusMinutes(30));
        localFunOrder.setGmtCreate(createTime);
        localFunOrder.setGmtModified(createTime);
        String inquiryNumber = generatorInquiryNumber();
        localFunOrder.setQueryNumber(inquiryNumber);

        Result<LocalFunResourceDetailDTO> result = iLocalFunResourceService.productDetail(localFunOrderInputCheckReq.getProductId());
        if(result.getData() != null){
            LocalFunResourceDetailDTO detail = result.getData();
            localFunOrder.setProductCityId(detail.getCityId());
            localFunOrder.setProductCityName(detail.getCityName());
            localFunOrder.setProductFunType(detail.getFunType());
            localFunOrder.setProductFunName(detail.getFunName());
            localFunOrder.setProductName(detail.getName());
        }
        //3.设置订单总额 = 应收总额 - 积分折扣 - 优惠折扣
        localFunOrder.setReceivableAmount(getOrderAmount(localFunOrder,localFunOrderInputCheckReq));
        localFunOrderMapper.insert(localFunOrder);

        try {
            // 下单完成后调用任务执行如果未付款则超时失效订单操作
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("id", orderId);
            // 延迟时间,单位毫秒,1800000L=30分钟后执行
            long delayMS = 1800000L;
            OhMyClient taskClient = new OhMyClient(domain, appName, password);
            ResultDTO<Long> resultTask = taskClient.runJob(jobId, jsonObject.toJSONString(), delayMS);

            if (resultTask.isSuccess()) {
                // 任务执行成功,过期时间*2是防止任务启动时redis数据已过期
                redisTemplate.opsForValue().set(RedisConstants.ORDER_INSTANCELD_KEY + orderId, resultTask.getData(), delayMS * 2, TimeUnit.MILLISECONDS);
            }
        } catch (Exception e) {
            log.error("当地玩乐订单-订单超时API任务异常：{}",e.getMessage());
        }
        return localFunOrder;
    }

    /**
     * 生成查询号码，六位随机数字字符串
     *
     * @return
     */
    public static String generatorInquiryNumber() {
        String randomNumber = String.valueOf((int) ((Math.random() * 9 + 1) * 100000));
        return randomNumber;
    }

    /**
     * 设置订单总额
     * @param localFunOrder
     * @return
     */
    private BigDecimal getOrderAmount(LocalFunOrder localFunOrder,LocalFunOrderInputCheckReq localFunOrderInputCheckReq) {
        // 积分费用
        BigDecimal integralFee = localFunOrder.getIntegralDeduction();
        // 应收总额
        BigDecimal receivableAmount = localFunOrder.getOrderAmount();
        //积分系统扣减积分
        if(!Objects.isNull(localFunOrder.getIntegral()) && localFunOrder.getIntegral() != 0){
            try {
                TransactionIntegralReq transactionIntegralReq = new TransactionIntegralReq();
                transactionIntegralReq.setCtsLogin(localFunOrderInputCheckReq.getCtsLogin());
                transactionIntegralReq.setCtsPassword(localFunOrderInputCheckReq.getCtsPassword());
                transactionIntegralReq.setOrderNumber(localFunOrder.getOrderNumber());
                transactionIntegralReq.setPoints(new BigDecimal(localFunOrder.getIntegral()));
                Result result = iStarVipBusinessService.transactionIntegral(transactionIntegralReq);
                if(result.getCode() != 1){
                    throw new BusinessException(SystemError.LOCAL_FUN_18011);
                }
            } catch (BusinessException e) {
                throw new BusinessException(SystemError.LOCAL_FUN_18011);
            }
        }

        //推广码
        try {
            if(StringUtil.isNotEmpty(localFunOrder.getCouponCode())){
                OperatePromotionQueryDTO promotionCode = findPromotionCode(localFunOrder);
                localFunOrder.setCouponDeduction(promotionCode.getReductionAmount());
            }
        } catch (Exception e) {
            log.error("获取推广码优惠失败:{}",e.getMessage());
        }
        // 最终订单总额=应收总额-积分扣减-优惠券扣减
        // 推广码优惠券费用
        BigDecimal couponDeduction = localFunOrder.getCouponDeduction();
        integralFee = Objects.isNull(integralFee) ? BigDecimal.ZERO : integralFee;
        couponDeduction = Objects.isNull(couponDeduction) ? BigDecimal.ZERO : localFunOrder.getCouponDeduction();
        return receivableAmount.subtract(integralFee).subtract(couponDeduction);
    }


    /**
     * 设置门票总额(单张门票价格*门票数)
     * @param singleTicketFee
     * @param num
     * @return
     */
    private BigDecimal getTicketsFee(BigDecimal singleTicketFee, Integer num) {
        return  singleTicketFee.multiply(BigDecimal.valueOf(num));
    }


    /**
     * 设置服务费(单服务费*门票数)
     * @param fee
     * @param serviceNum
     * @return
     */
    private BigDecimal getServiceFee(BigDecimal fee, Integer serviceNum) {
        // 总服务费
        if(null != serviceNum && null != fee){
            return fee.multiply(BigDecimal.valueOf(serviceNum));
        }else {
            return BigDecimal.ZERO;
        }
    }

    /**
     * 登记旅客资料
     * @param touristInfos   入参旅客信息
     * @param userId                     用户ID
     * @param orderId                    订单ID
     * @param productId
     * @param localFunOrder
     */
    private void registerTouristInfo(List<LocalFunOrderTouristInputCheckReq> touristInfos, Long userId, long orderId, Long attrId1, Long attrId2, Long productId, LocalFunOrderInfo localFunOrder) {
        if(CollectionUtils.isNotEmpty(touristInfos)){
            LocalFunOrderTourist localFunOrderTourist;
            for (LocalFunOrderTouristInputCheckReq touristInfo : touristInfos) {
                localFunOrderTourist = EntityUtil.copy(touristInfo,LocalFunOrderTourist.class);
                localFunOrderTourist.setId(SnowflakeIdWorker.nextId());
                localFunOrderTourist.setOrderId(orderId);
                localFunOrderTourist.setCreateId(userId);

                //获取对应的金额和服务费
                try {
                    LocalFunProductTicketDTO localFunProductTicketDTO = iLocalFunCostPriceService.getLocalFunProductTicketDTO(attrId1+","+attrId2,productId,userId,LocalDateTime.now());
                    if(localFunProductTicketDTO != null){
                        localFunOrderTourist.setSinglePrice(localFunOrder.getSinglePrice()==null?BigDecimal.ZERO:localFunOrder.getSinglePrice());
                        localFunOrderTourist.setCharge(localFunOrder.getChargePrice()==null?BigDecimal.ZERO:localFunOrder.getChargePrice());
                    }
                } catch (Exception e) {
                    log.error("记录旅客票价信息失败");
                }

                localFunOrderTouristMapper.insert(localFunOrderTourist);
            }
        }
    }
}
